{"record":{"id":"0415f64cca2996bf","repo":"gastownhall/beads","slug":"re-key-id-s-s-w-0415f6","errorCode":null,"errorMessage":"re-key id %s -> %s: %w","messagePattern":"re-key id (.+?) -> (.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/schema/dep_id_backfill.go","lineNumber":90,"sourceCode":"\t\tif !target.Valid {\n\t\t\t// Malformed row with no target (ck_dep_one_target should prevent this);\n\t\t\t// leave it untouched for `bd doctor` to surface rather than guessing.\n\t\t\tcontinue\n\t\t}\n\t\tif want := depid.New(issueID, target.String); want != id {\n\t\t\ttodo = append(todo, rekey{oldID: id, newID: want})\n\t\t}\n\t}\n\t_ = rows.Close()\n\tif err := rows.Err(); err != nil {\n\t\treturn false, err\n\t}\n\n\tfor _, r := range todo {\n\t\t//nolint:gosec // G201: table is a hardcoded constant, never user input.\n\t\tif _, err := db.ExecContext(ctx, fmt.Sprintf(`UPDATE %s SET id = ? WHERE id = ?`, table),\n\t\t\tr.newID, r.oldID); err != nil {\n\t\t\treturn true, fmt.Errorf(\"re-key id %s -> %s: %w\", r.oldID, r.newID, err)\n\t\t}\n\t}\n\treturn len(todo) > 0, nil\n}\n\n// columnExists reports whether table.column is present in the current schema.\nfunc columnExists(ctx context.Context, db DBConn, table, column string) (bool, error) {\n\tvar count int\n\tif err := db.QueryRowContext(ctx,\n\t\t`SELECT COUNT(*) FROM INFORMATION_SCHEMA.COLUMNS\n\t\t WHERE TABLE_SCHEMA = DATABASE() AND TABLE_NAME = ? AND COLUMN_NAME = ?`,\n\t\ttable, column).Scan(&count); err != nil {\n\t\treturn false, err\n\t}\n\treturn count > 0, nil\n}\n","sourceCodeStart":72,"sourceCodeEnd":107,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/schema/dep_id_backfill.go#L72-L107","documentation":"The per-row failure of the re-key loop: an UPDATE <table> SET id = ? WHERE id = ? failed while rewriting one dependency edge from its old (random UUID) id to the deterministic depid value. The message names both ids so the exact offending row is identifiable. Any row already at its deterministic id is skipped, so this only fires on genuinely divergent rows.","triggerScenarios":"The UPDATE statement for a specific (oldID → newID) pair errors: most commonly a unique-key collision (another row already holds newID — duplicate edges), a foreign-key reference still pointing at oldID, connection loss, or lock contention with a concurrent writer.","commonSituations":"Two identical dependency edges exist with different random UUIDs — the first UPDATE wins, the second collides on the deterministic id; a foreign key on dependencies.id blocks the rename; Dolt server under concurrent migration from a peer.","solutions":["Deduplicate edges first: find rows sharing (issue_id, target) and delete extras so only one row can claim each deterministic id","Check for foreign keys or unique keys referencing the old id and resolve/update them before re-keying","Retry the migration — already-updated rows are skipped, so it resumes at the failed row","Inspect the row by id (`SELECT * FROM dependencies WHERE id = '<oldID>'`) to confirm its shape before manual fixes"],"exampleFix":"-- before: duplicate edges with different random ids collide\nDELETE d1 FROM dependencies d1 JOIN dependencies d2\n  ON d1.issue_id = d2.issue_id\n AND COALESCE(d1.depends_on_issue_id, d1.depends_on_wisp_id, d1.depends_on_external) =\n     COALESCE(d2.depends_on_issue_id, d2.depends_on_wisp_id, d2.depends_on_external)\n AND d1.id > d2.id;\n-- after: re-run migration; remaining row re-keys cleanly","handlingStrategy":"validation","validationCode":"-- before rekey, ensure no row already occupies the target deterministic id\nSELECT COUNT(*) FROM dependencies WHERE id = '<expected deterministic id>';","typeGuard":null,"tryCatchPattern":"if _, err := db.Exec(\"UPDATE dependencies SET id = ? WHERE id = ?\", newID, oldID); err != nil {\n    if dberrors.IsUniqueViolation(err) {\n        // delete/merge the duplicate edge holding newID, then retry\n    }\n    return err\n}","preventionTips":["Deduplicate dependency edges sharing (issue_id, target) before migration","Avoid concurrent writers during migration passes","The message names old→new ids — look the row up directly to diagnose"],"tags":["go","dolt","migration","update","unique-key"],"backgroundTag":"dependency-id-rekey-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}