{"record":{"id":"56a374dad471e2cc","repo":"gastownhall/beads","slug":"wisp-dependencies-w","errorCode":null,"errorMessage":"wisp_dependencies: %w","messagePattern":"wisp_dependencies: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/dep_id_backfill.go","lineNumber":36,"sourceCode":"// id. Leaving them would keep two independently-migrated clones divergent (same\n// edge, different primary key) and break `bd dolt pull`. This rewrites them to\n// the deterministic value so two clones converge to byte-identical dependencies.\n//\n// It runs from MigrateUp right after the schema migrations (so 0050 has already\n// asserted the canonical schema), and only on a pass where migration work was\n// needed — it is not part of the steady-state open path. It is idempotent: a row\n// already keyed deterministically is skipped, so re-running on a later migration\n// pass is a cheap no-op. dependencies changes are staged and committed by\n// MigrateUp; wisp_dependencies is dolt-ignored, so its re-key stays clone-local\n// (it only escapes on promotion, which copies the id).\nfunc rekeyDependencyIDs(ctx context.Context, db DBConn) (bool, error) {\n\twroteDeps, err := rekeyDependencyTable(ctx, db, \"dependencies\")\n\tif err != nil {\n\t\treturn wroteDeps, fmt.Errorf(\"dependencies: %w\", err)\n\t}\n\twroteWisp, err := rekeyDependencyTable(ctx, db, \"wisp_dependencies\")\n\tif err != nil {\n\t\treturn wroteDeps || wroteWisp, fmt.Errorf(\"wisp_dependencies: %w\", err)\n\t}\n\treturn wroteDeps || wroteWisp, nil\n}\n\n// rekeyDependencyTable re-derives ids for one edge table. table must be a\n// hardcoded constant (\"dependencies\" or \"wisp_dependencies\").\nfunc rekeyDependencyTable(ctx context.Context, db DBConn, table string) (bool, error) {\n\t// Skip cleanly if the table or its id column isn't present (e.g. an older or\n\t// partial schema where the surrogate key was never added): nothing to re-key.\n\thasID, err := columnExists(ctx, db, table, \"id\")\n\tif err != nil {\n\t\treturn false, err\n\t}\n\tif !hasID {\n\t\treturn false, nil\n\t}\n\n\t// The natural target is the single non-null of the three typed columns —","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/dep_id_backfill.go#L18-L54","documentation":"Same family as the dependencies error but for wisp_dependencies: rekeyDependencyIDs wraps failures from re-keying the wisp_dependencies edge table. Note wisp_dependencies is dolt-ignored, so this re-key stays clone-local and does not participate in pull-based convergence — a failure here affects only the local clone.","triggerScenarios":"rekeyDependencyTable(ctx, db, \"wisp_dependencies\") fails — the same failure modes as the dependencies pass: schema probe error, SELECT failure, scan error, or an UPDATE re-key failing (e.g. unique-key collision on depid-derived ids).","commonSituations":"Old clones carrying UUID-keyed wisp rows from before migration 0050; connection drops mid-migration; duplicate wisp edges resolving to the same deterministic id; partial/older schema lacking the typed target columns.","solutions":["Inspect the wrapped inner error for the specific failing statement","Check for duplicate wisp edges that would collide on the deterministic id and deduplicate them","Re-run the migration pass — the re-key is idempotent","If wisp_dependencies lacks the id column (older schema), the pass skips cleanly; verify with the INFORMATION_SCHEMA.COLUMNS query"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"-- same preflight for wisp_dependencies (clone-local)\nSELECT issue_id, COALESCE(depends_on_issue_id, depends_on_wisp_id, depends_on_external) t, COUNT(*) c\nFROM wisp_dependencies GROUP BY issue_id, t HAVING c > 1;","typeGuard":null,"tryCatchPattern":"if _, err := rekeyDependencyIDs(ctx, db); err != nil {\n    if dberrors.IsUniqueViolation(err) {\n        return fmt.Errorf(\"dedupe wisp edges: %w\", err)\n    }\n    return err\n}","preventionTips":["Remember wisp_dependencies rekeys are clone-local — fix per clone","Apply migrations in order (0043 → 0050) before backfill runs","Verify the id column exists on older schemas (the pass skips otherwise)"],"tags":["go","dolt","migration","wisp-dependencies","backfill"],"backgroundTag":"dependency-id-rekey-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}