{"record":{"id":"c26e3069924caba2","repo":"gastownhall/beads","slug":"orphan-dependency-s-s","errorCode":null,"errorMessage":"orphan dependency %s -> %s","messagePattern":"orphan dependency (.+?) -> (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/migration/legacysqlite/reader.go","lineNumber":905,"sourceCode":"\t\tcurrentString{\"dependency type\", typ},\n\t\tcurrentString{\"dependency created_by\", by},\n\t); err != nil {\n\t\treturn err\n\t}\n\tif err := checkCurrentVarchars(\n\t\tcurrentVarchar{\"dependency issue_id\", id, types.MaxFieldLen},\n\t\tcurrentVarchar{\"dependency depends_on_id\", to, types.MaxFieldLen},\n\t\tcurrentVarchar{\"dependency type\", typ, currentShortVarcharRunes},\n\t\tcurrentVarchar{\"dependency created_by\", by, types.MaxFieldLen},\n\t); err != nil {\n\t\treturn err\n\t}\n\tif by == \"\" {\n\t\treturn fmt.Errorf(\"dependency created_by is empty for %s -> %s\", id, to)\n\t}\n\tissue := byID[id]\n\tif issue == nil || byID[to] == nil {\n\t\treturn fmt.Errorf(\"orphan dependency %s -> %s\", id, to)\n\t}\n\tif issue.Ephemeral != byID[to].Ephemeral {\n\t\treturn fmt.Errorf(\"dependency %s -> %s crosses ephemeral storage\", id, to)\n\t}\n\tkey := id + \"\\x00\" + to\n\tif seenDeps[key] {\n\t\treturn fmt.Errorf(\"multiple legacy dependencies for %s -> %s\", id, to)\n\t}\n\tseenDeps[key] = true\n\tcreated, e := parseTime(at)\n\tif e != nil {\n\t\treturn e\n\t}\n\tif created.IsZero() {\n\t\treturn fmt.Errorf(\"dependency created_at is zero for %s -> %s\", id, to)\n\t}\n\tif (metadata.Valid && metadata.String != \"\") || (thread.Valid && thread.String != \"\") {\n\t\treturn fmt.Errorf(\"dependency %s -> %s uses unsupported metadata or thread ID\", id, to)","sourceCodeStart":887,"sourceCodeEnd":923,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/migration/legacysqlite/reader.go#L887-L923","documentation":"A dependency row references an issue_id or depends_on_id that does not exist among the loaded issues (byID map). The reader refuses to import dangling dependency edges because they would violate the current database's foreign-key integrity and produce a broken dependency graph.","triggerScenarios":"The legacy SQLite dependencies table contains an edge whose either endpoint was deleted (or renamed) without removing the edge, detected in appendLegacyDependencyRow when byID[id] or byID[to] is nil after the created_by check.","commonSituations":"Legacy versions without foreign-key enforcement deleting issues directly via SQL; bulk cleanup scripts that removed issues but left dependencies; corrupted databases from crashed old versions; test fixtures with hand-written inconsistent edges.","solutions":["Remove dangling edges before migrating: DELETE FROM dependencies WHERE issue_id NOT IN (SELECT id FROM issues) OR depends_on_id NOT IN (SELECT id FROM issues).","If the edge is still meaningful, re-point the missing endpoint to the correct existing issue ID.","Run PRAGMA foreign_key_check on the legacy DB to enumerate all integrity violations in one pass.","Fix the deletion workflow that produced orphans (enable FK enforcement or always clean child rows) so it does not recur."],"exampleFix":"// before: edges pointing at deleted issues\nDELETE FROM dependencies WHERE issue_id NOT IN (SELECT id FROM issues) OR depends_on_id NOT IN (SELECT id FROM issues);\n// after: all endpoints resolve","handlingStrategy":"validation","validationCode":"rows, err := legacyDB.Query(`SELECT issue_id, depends_on_id FROM dependencies\n  WHERE issue_id NOT IN (SELECT id FROM issues)\n     OR depends_on_id NOT IN (SELECT id FROM issues)`)\n// delete or re-point these dangling edges before migrating","typeGuard":null,"tryCatchPattern":"if err := migrateLegacy(db); err != nil {\n    if strings.Contains(err.Error(), \"orphan dependency\") {\n        return fmt.Errorf(\"remove dangling dependency edges and retry: %w\", err)\n    }\n    return err\n}","preventionTips":["Enable PRAGMA foreign_keys = ON on the legacy database to prevent dangling edges at write time.","Run PRAGMA foreign_key_check as a pre-migration integrity gate.","Clean up dependencies whenever issues are deleted or IDs change."],"tags":["migration","sqlite","referential-integrity","dependency"],"backgroundTag":"orphan-foreign-key","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}