UID Lookup

Navigate to a record by its persistent UID

A UID (_UID in GEDCOM 5.5.1, UID in GEDCOM 7.0) is a persistent identifier assigned to a record. The UID survives XREF renumbering and tree migrations, making it a stable reference point.

This feature allows navigating directly to a record by its UID. The URL pattern is:

  • /tree/{tree}/goto-uid/{uid} — scoped to one tree
  • /goto-uid/{uid} — global (searches all trees)

Behavior:

  • 0 hits → 404
  • 1 visible hit → redirect to the record
  • >1 visible hit → selection list (case-variant UIDs or the same UID in multiple records)

UID comparison is case-insensitive (GEDCOM specs do not define UID as case-sensitive). The stored value is verbatim; matching is done case-insensitively so that case-variant UIDs return a selection list rather than a possibly-wrong single redirect.

You can look up UIDs via the quick search input. For shorter UIDs that can be regarded as XREFs, the prefix uid: can be added to the search value.

Standard navigation (goto-id)

goto-id is the standard navigation target for every linkenhancer link — both untyped (wt=@REF@) and typed (wt=<type>@REF@) — and resolves a reference that is either a record XREF or a UID. The URL pattern is:

  • /tree/{tree}/goto-id/{id} — scoped to one tree (falls back to a global lookup when nothing is found in the tree, with a flash notice)
  • /goto-id/{id} — global (searches all trees)

Behavior (shared IdResolver): the id is tried length-aware and bidirectionally — a long id (≥ 18 chars) as a UID first, a short one as an XREF first — and falls back to the other when the first yields nothing, so a resolution is never lost. 0 hits → 404, 1 visible hit → redirect, >1 → selection list.

sequenceDiagram
    autonumber
    participant U as 👤 User (Browser)
    participant JS as LE JavaScript
    participant WT as webtrees Server
    participant IR as IdResolver
    participant DB as Database

    Note over U,JS: Click on an LE link
    U->>JS: Click on #@wt=@I234@
    JS->>JS: detect href "#@…"
    JS->>WT: GET /tree/5/goto-id/I234
    WT->>IR: resolve("I234", tree=5)

    alt ID short (< 18 chars) → try as XREF first
        IR->>DB: SELECT … WHERE xref = 'I234'
        DB-->>IR: Match?
    else ID long (>= 18 chars) → try as UID first
        IR->>DB: SELECT … FROM le_uid_index WHERE uid = '…'
        DB-->>IR: Match?
    end

    alt ✅ 1 match
        IR-->>WT: Record
        WT-->>U: Redirect to record page
    else 0 matches → Fallback
        IR->>IR: try the other direction (XREF ⇄ UID)
    else >1 matches
        WT-->>U: selection list
    end

    Note over IR,DB: Bidirectional — XREF ⇄ UID<br/>a lookup is never lost

A typed wt=<type>@REF@ link is a legacy form: the type letter is no longer used for routing (all links go through goto-id) and is only documentary — it still drives the diagram link for individuals and the type-mismatch hint in the cross-reference overview. New links should use the untyped wt=@REF@ form.

XREF route (goto-xref)

There is also the route /tree/{tree}/goto-xref/{xref} available, which allows you to navigate to the corresponding record in the tree, regardless of the record type.

Cross-reference overview: UID targets in other trees

In the admin Cross-Reference Overview a link whose UID target is not found in the record’s own tree is normally shown as “target not found”. When the UID feature is enabled, such a target is additionally resolved globally (across the other trees); if matches exist it is rendered as not unique (?) with the match count instead: up to 3 matches are listed as direct cross-tree links, more than 3 collapse into a single goto-id link (title = the UID). This behavior is hard-gated on the UID feature preference and never applies to targets that name an explicit tree.

Index

The UID index is stored in the le_uid_index table (one row per UID tag occurrence, distinguished by tag_path). It is maintained exclusively by build-uid-index.php (no live scan on request).

  • Initial build (first run, or --rebuild): full scan of all GEDCOM tables, extracting all UID tags via UidTagCollector.
  • Incremental runs: only records whose MD5 fingerprint changed (or were added/removed) are re-scanned.

Cron example (every 10 minutes, up to 5000 records per run):

*/10 * * * * cd /path/to/webtrees && php modules_v4/linkenhancer/cli/build-uid-index.php --limit=5000 >> /var/log/linkenhancer-uid-index.log 2>&1

The feature can be toggled on/off in the module admin page (“Activate Support” → [5] UID lookup). The current index status (row count, last build time) is shown there.

While the feature is switched off, index builds are skipped automatically (the cron run exits 0 without doing work). --force builds the index anyway (e.g. to prepare for re-enabling), and --flush works regardless of the switch.

Note: UID tags at any nesting level are indexed (e.g. 0 @I1@ INDI, 1 _UID, 1 FAMF, 2 _UID). The tag path is stored per row so duplicates are distinguishable in the selection list.

Last modified November 2, 2026: applied repoFileURL, where applicable (21fa655)