Skip to content

A dump rewrites the ids of Artefact and ABOUT rows, so restore reads it - #607

Merged
danbarua merged 1 commit into
mainfrom
fix/dump-restore-first-graph-label
Sep 30, 2026
Merged

danbarua merged 1 commit into
mainfrom
fix/dump-restore-first-graph-label

Conversation

@danbarua

Copy link
Copy Markdown
Owner

What was wrong

labkit restore could not read a file labkit dump had just written once the record held an artefact:

invalid value for type graphid: "3659174697238529" [22P02]

The first failing line was INSERT INTO labkit_t1."Artefact" VALUES ('3659174697238529', '{...}').

Cause

AGE's graphid has no text input, so restorable in packages/core-db/dump.ts rewrites the id columns of every graph table's rows to ag_catalog._graphid(label, entry). It finds the graph tables with a CREATE TABLE ... INHERITS (..._ag_label_vertex|edge) pattern whose body was [\s\S]*?, which can run past the statement's own ;.

pg_dump orders tables by name, and _ag_label_vertex and _ag_label_edge (which have no INHERITS) come directly before Artefact and ABOUT. Each of those two matched through to the next table's INHERITS clause, so it was recorded under the wrong name, and Artefact and ABOUT were never recognised as graph tables. Their rows kept the text literal. drizzle.__drizzle_migrations did the same to _ag_label_edge. The other labels were unaffected, which is why a record holding only questions, enquiries and notes round-tripped.

Fix

The table body is [^;]*, so a match cannot run into the next statement. This is a one-line change to the pattern.

Ruled out, measured

  • Setting search_path = ag_catalog, "$user", public before the dump runs, or again after its set_config('search_path', '', false), with a dump written before the fix: the restore still fails with the same error.
  • A fresh record with provisionTenantGraph run for labkit_t1: '3659174697238529'::ag_catalog.graphid and the raw INSERT both fail with the same error; INSERT ... VALUES (ag_catalog._graphid(13, 1), '{}') succeeds.

Test

tests/persistence/dump-restore.test.ts gains a test that writes an Artefact, a Claim, a CriterionEvaluation and an ABOUT edge, dumps and restores them, and checks that entityAsHal returns the same result for each handle before and after. It also checks that no graph-table INSERT in the dump still starts with a text id. Without the fix it fails (1 pass, 1 fail); with the fix, 2 pass.

Round trip with the compiled binary

After bun run cli:build, open + observe + note into record a, dump, restore into b, then compare get and why output between the two records:

Q_1
LOE_1
ART_2
EV_2
EU_2
NOTE_3
labkit: wrote .../restore/d.sql (168KB)
labkit: restored .../restore/d.sql to .../restore/b/.labkit/pglite
restore exit=0
get Q_1: identical (6 lines)
get LOE_1: identical (8 lines)
get ART_2: identical (6 lines)
get EV_2: identical (7 lines)
get EU_2: identical (6 lines)
get NOTE_3: identical (3 lines)
why LOE_1: identical
--- restored: get ART_2
ART_2  Artefact

  kind           observations
  logical_name   runs.parquet

  evidence:recorded_in     EV_2

bun run check:quick: all 25 passed.

A dump written before this change still contains the text ids, so it still fails to restore. Restoring it needs a fresh dump from the source record.

🤖 Generated with Claude Code

https://claude.ai/code/session_01FWZHuy7xJbVqxyLipnvwdY

The pattern that finds graph tables in a dump let a table's body run past its
own `;`. `_ag_label_vertex` and `_ag_label_edge` have no INHERITS clause, so
each matched through to the next table's clause and hid it: `Artefact` and
`ABOUT` were never recognised as graph tables, their ids stayed as text, and
AGE's graphid rejects text input. The body now stops at the statement's `;`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FWZHuy7xJbVqxyLipnvwdY
@github-actions github-actions Bot added the area:record The record: core-domain, core-db, the CLI, the MCP server, the domain model and workspaces label Sep 30, 2026
@danbarua
danbarua enabled auto-merge (squash) September 30, 2026 23:24
@danbarua
danbarua merged commit f07b127 into main Sep 30, 2026
10 checks passed
@danbarua
danbarua deleted the fix/dump-restore-first-graph-label branch September 30, 2026 23:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:record The record: core-domain, core-db, the CLI, the MCP server, the domain model and workspaces

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant