{"record":{"id":"d4264ce7ce6c5268","repo":"gastownhall/beads","slug":"orphan-label-for-s","errorCode":null,"errorMessage":"orphan label for %s","messagePattern":"orphan label for (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/migration/legacysqlite/reader.go","lineNumber":852,"sourceCode":"\t\tvar id, label string\n\t\tif err := labels.Scan(&id, &label); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := checkUTF8(\n\t\t\tcurrentString{\"label issue_id\", id},\n\t\t\tcurrentString{\"label\", label},\n\t\t); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tif err := checkCurrentVarchars(\n\t\t\tcurrentVarchar{\"label issue_id\", id, types.MaxFieldLen},\n\t\t\tcurrentVarchar{\"label\", label, types.MaxFieldLen},\n\t\t); err != nil {\n\t\t\treturn err\n\t\t}\n\t\tissue := byID[id]\n\t\tif issue == nil {\n\t\t\treturn fmt.Errorf(\"orphan label for %s\", id)\n\t\t}\n\t\tissue.Labels = append(issue.Labels, label)\n\t}\n\treturn labels.Err()\n}\n\nfunc loadDependencies(ctx context.Context, db *sql.Tx, byID map[string]*types.Issue) error {\n\tdeps, err := db.QueryContext(ctx, \"SELECT issue_id,depends_on_id,type,CAST(created_at AS TEXT),created_by,metadata,thread_id FROM dependencies ORDER BY issue_id,depends_on_id,type\")\n\tif err != nil {\n\t\treturn err\n\t}\n\tdefer deps.Close()\n\tseenDeps := make(map[string]bool)\n\tfor deps.Next() {\n\t\tif err := appendLegacyDependencyRow(deps, byID, seenDeps); err != nil {\n\t\t\treturn err\n\t\t}\n\t}","sourceCodeStart":834,"sourceCodeEnd":870,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/migration/legacysqlite/reader.go#L834-L870","documentation":"While loading labels during legacy migration, a labels row references an issue_id that has no corresponding issue in the loaded set (byID lookup returned nil). The reader treats referential integrity violations as fatal import errors rather than silently dropping orphaned labels, since the legacy database is expected to be consistent.","triggerScenarios":"The legacy SQLite labels table contains a row whose issue_id does not exist in the issues table — e.g. the issue was deleted without deleting its labels, or labels were inserted for an issue ID that was later changed. Raised in loadLabels after id/label pass UTF-8 and VARCHAR checks.","commonSituations":"Legacy databases from old bd versions that lacked foreign-key enforcement; manual DELETE FROM issues without cleaning labels; interrupted transactions that removed issues but not child rows; direct SQLite manipulation.","solutions":["Delete the orphaned label rows before migrating: DELETE FROM labels WHERE issue_id NOT IN (SELECT id FROM issues).","If the label should survive, fix the issue_id to point at a real issue instead of deleting it.","Run a full orphan sweep over child tables (labels, dependencies, comments) with NOT IN subqueries to catch all referential breaks at once.","Verify PRAGMA foreign_key_check on the legacy DB to surface all integrity violations before migration."],"exampleFix":"// before: labels referencing deleted issues\nDELETE FROM labels WHERE issue_id NOT IN (SELECT id FROM issues);\n// after: no orphan labels remain","handlingStrategy":"validation","validationCode":"// before migration, ensure referential integrity\nrows, err := legacyDB.Query(`SELECT COUNT(*) FROM labels WHERE issue_id NOT IN (SELECT id FROM issues)`)\n// if count > 0, delete or repair orphans first","typeGuard":null,"tryCatchPattern":"if err := migrateLegacy(db); err != nil {\n    if strings.Contains(err.Error(), \"orphan label for\") {\n        // id is in the message; remove that labels row and retry\n        return fmt.Errorf(\"clean orphan labels and retry: %w\", err)\n    }\n    return err\n}","preventionTips":["Always delete child rows (labels, dependencies, comments) when deleting issues, even if FKs are off.","Run PRAGMA foreign_key_check on the legacy DB before migrating.","Avoid direct SQL deletes on the legacy database; use bd commands that maintain integrity."],"tags":["migration","sqlite","referential-integrity","data-integrity"],"backgroundTag":"orphan-foreign-key","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}