Skip to the tool

How to find every broken pointer in a GEDCOM

A pointer to a record that does not exist is a fatal error, not a warning. Find all of them, then choose delete, repoint or placeholder for each.

Intermediate20 minutesChecked against the tools on 3 Sep 2026Uses GEDCOM Validator, Broken Link Repair and Link Reciprocity Checker

find-every-broken-pointer-in-a-gedcom.md, 8,594 characters. The same bytes answer at /how-to/find-every-broken-pointer-in-a-gedcom.md.

The importer said there is no INDI with that pointer, or it listed a family whose child does not exist, or it stopped without saying anything and half the tree arrived.

A GEDCOM holds its relationships as pointers. A family record says 1 CHIL @I5@ and expects a record starting 0 @I5@ INDI somewhere else in the file. When that record is absent the pointer dangles. The 5.5.5 specification calls this fatal rather than advisory, and a strict importer is entitled to refuse the whole file over one of them.

What causes it

Four ways a pointer loses its target, and they need different repairs.

A record was deleted and the pointers to it were not. The commonest. Delete a person in a program that does not sweep, export, and every family that listed them now points at nothing.

A file was cut. A truncated transfer removes the tail of the file. Every pointer into the missing tail dangles at once, and the count is large.

Letter case. @i5@ and @I5@ are different xrefs. A hand edit or a merge that lower-cased one side produces a pointer that looks right and resolves to nothing.

The link runs one way. @I5@ says FAMC @F1@ and @F1@ never lists @I5@ as a child. Both records exist, so no pointer is broken, and the relationship is invisible from one side. Most importers read families from the FAM record, so this person quietly loses their parents.

The last one is not a dangling pointer and most validators do not report it. It needs its own check.

Flowchart with 11 labelled steps. The same steps are written out under Diagram source.
Diagram source
flowchart TD
  S["An importer complained about a pointer"] --> V["GEDCOM Validator: filter category to referential"]
  V --> Q{"Which code?"}
  Q -- "dangling-pointer" --> B["Broken Link Repair"]
  Q -- "link-not-reciprocated" --> C["Link Reciprocity Checker"]
  Q -- "pointer-type or void-pointer" --> T["The target exists but is the wrong kind of record"]
  B --> K{"Is there a candidate target?"}
  K -- "differs by letter case only" --> RP["Repoint"]
  K -- "none, and the line is load-bearing" --> PL["Placeholder, so the family keeps its member"]
  K -- "none, and nothing else records it" --> DL["Delete the line"]
  C --> AD["Add the reciprocal pointer"]

The run

Numbers below are from fixtures/public/broken-links-b5.ged, a 723-byte file holding 11 records and 13 pointers.

  1. Open GEDCOM Validator and drop the file. The three counts across the top read errors 5, warnings 3, infos 2.
  2. Read the category table under the counts. On this file referential holds 7 and logical holds 3. Click referential in the left column to filter to it.
  3. Set the code select to dangling-pointer (5). Every remaining row is a pointer with no target.
  4. Read the rows. Each names a line, an xref and the pointer: FAMC points to @F77@, no record with xref @F77@ exists at line 19, SOUR points to @S88@ at line 26, OBJE points to @M42@ at line 31, CHIL points to @i5@ at line 39 and CHIL points to @I99@ at line 40. The GEDCOM Validator on broken-links-b5.ged: 5 errors, 3 warnings, 2 infos, the category table with 7 referential, and the dangling-pointer rows.
  5. Open Broken Link Repair and drop the same file. The header line reads 13 pointers across 11 records, then 5 broken pointers and 3 orphaned records.
  6. Read the Broken links list. Each card names the record and pointer, a no such record badge, the confidence and the line, its recommendation on the right, and a Repair select that starts at leave as is.
  7. Read the card for line 39, CHIL @i5@. As loaded it says recommended: repoint and three rationale lines, the first @F1@ line 39 points at @i5@; no record defines that xref. Set its Repair select to Repoint @F1@ line 39 from @i5@ to @I5@ (recommended). The card then adds the diff, - 1 CHIL @i5@ above + 1 CHIL @I5@, two more rationale lines, @I5@ differs from @i5@ in letter case only and @I5@ is an INDI record, which is what CHIL names, and Repair confidence 90%. That is the case fault, found and fixed without you noticing the capital.
  8. Read the card for line 40, CHIL @I99@. No candidate exists, and a load bearing badge sits beside the line number because @F1@ is a family record and CHIL is part of its shape; deleting the line drops a member of the family. Its recommendation reads recommended: placeholder, offered at 0.70 against delete at 0.60. Take the placeholder when you know a child existed and the record is gone. Broken Link Repair on the same file: the CHIL @i5@ card recommending a repoint, the load-bearing CHIL @I99@ card recommending a placeholder, and the three orphaned records below them.
  9. Press Select recommended repairs to take every recommendation at once, or set each Repair select yourself. The primary button then reads Apply 5 repairs, quarantine 0.
  10. Read Orphaned records below. On this file it lists 3, with Select all 3 and Clear above them: @I7@ INDI as person in no family at 75%, @S9@ SOUR as source nobody cites at 90%, and @N4@ NOTE as note nothing references at 90%. Nothing points at them. Ticking one and applying puts it in a quarantine block inside the exported file, which the same tool restores with Restore quarantined records.
  11. Open Link Reciprocity Checker and drop the file. The header line reads 10 pointers checked across 5 individuals and 1 families, then 4 one-way pointers, and the badges below read 3 orphaned pointer and 1 incomplete entry.
  12. Read the incomplete-entry finding: @I5@ has FAMC @F1@ but @F1@ lists 3 CHIL, none of them @I5@, at 0.80. Both records exist, so no validator error fired, and @I5@ has no parents from the family's side. Its Repair select starts at leave as is; choose the add option, then press Apply 1 fix and build file under Fix.

What to check when it worked

  • GEDCOM Validator on the repaired file reports 0 rows under code dangling-pointer.
  • Broken Link Repair reports Every pointer names a record that exists. in its header line.
  • Link Reciprocity Checker reports 0 for incomplete-entry, or every remaining one is a deliberate one-way link.
  • The person counts did not fall. A repair that deletes a load-bearing CHIL line removes a child from a family, and the family is smaller by one.
  • The importer that refused the file accepts it.

What to do when it did not

The dangling count is in the hundreds and they share a prefix. The file was cut. Every pointer into the missing tail dangles at once. Run File Inspector and compare Records by type against what you expect; then GEDCOM error messages, decoded covers the truncation case.

A pointer resolves but the validator still complains. Read the code. pointer-type means the target exists and is the wrong kind of record, such as a CHIL naming a SOUR. void-pointer means the file wrote @VOID@ on purpose, which 7.0 allows and 5.5.1 does not.

Repointing produced a person in two families. The candidate matched on letter case and the two records were genuinely different people. Reload the page to start from the file as it came in, and choose the placeholder instead.

You are on GEDCOM 7.0 and want a conformance check, not a pointer check. The specification authors publish their own browser-local checker at gedcom7code.github.io/js-gedcom. Use it for 7.0 conformance and this page for the pointer graph.

Related