{"record":{"id":"33e23f665d54539a","repo":"gastownhall/beads","slug":"update-issue-id-w","errorCode":null,"errorMessage":"update issue ID: %w","messagePattern":"update issue ID: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/bulk_ops.go","lineNumber":301,"sourceCode":"\t\tif target == oldID {\n\t\t\ttarget = newID\n\t\t}\n\t\tif err := RecordDepEventInTx(ctx, tx, EventDepAdd, source, edge.kind, target, edge.metadata, actor); err != nil {\n\t\t\treturn err\n\t\t}\n\t}\n\treturn nil\n}\n\nfunc updateIssueIDInTx(ctx context.Context, tx *sql.Tx, oldID, newID string, issue *types.Issue, actor string) error {\n\tnow := time.Now().UTC()\n\tresult, err := tx.ExecContext(ctx, `\n\t\tUPDATE issues\n\t\tSET id = ?, title = ?, description = ?, design = ?, acceptance_criteria = ?, notes = ?, updated_at = ?\n\t\tWHERE id = ?\n\t`, newID, issue.Title, issue.Description, issue.Design, issue.AcceptanceCriteria, issue.Notes, now, oldID)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"update issue ID: %w\", err)\n\t}\n\tif rows, _ := result.RowsAffected(); rows == 0 {\n\t\treturn fmt.Errorf(\"issue not found: %s\", oldID)\n\t}\n\n\tif err := UpdateIssueIDInDependenciesInTx(ctx, tx, oldID, newID); err != nil {\n\t\treturn err\n\t}\n\n\t// A live lease follows its issue across the rename.\n\tif _, err := tx.ExecContext(ctx,\n\t\t`UPDATE leases SET issue_id = ? WHERE issue_id = ?`, newID, oldID); err != nil {\n\t\treturn fmt.Errorf(\"rename lease row: %w\", err)\n\t}\n\n\treturn InsertDerivedEvent(ctx, tx, \"events\", AuxEvent{\n\t\tIssueID:   newID,\n\t\tEventType: \"renamed\",","sourceCodeStart":283,"sourceCodeEnd":319,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/bulk_ops.go#L283-L319","documentation":"This error means the SQL UPDATE that moves an issue row to its new ID (and rewrites its fields) failed at the driver level. It wraps the raw database error, so the cause is typically a constraint violation or a connection problem. The rename transaction is aborted, leaving the old ID intact.","triggerScenarios":"Calling UpdateIssueIDInTx where `UPDATE issues SET id = ? ...` fails — e.g. newID already exists (primary-key/unique violation), newID empty or malformed violating a CHECK, or the driver errors on the statement.","commonSituations":"Renaming to an ID that collides with an existing issue; renaming to an ID containing invalid characters under a strict schema; DB connection dropped mid-transaction; schema out of sync with the code.","solutions":["Check that newID does not already exist before renaming (SELECT or the library's Exists helper).","Validate the new ID format (prefix, allowed characters, non-empty) before calling UpdateIssueID.","Read the wrapped driver error to identify the exact constraint and address it.","Ensure schema migrations are current, then retry the rename in a fresh transaction."],"exampleFix":"// before\nstore.UpdateIssueID(ctx, \"bd-1\", \"bd-2\", issue, actor) // bd-2 already exists -> constraint violation\n// after\nif exists, _ := store.GetIssue(ctx, \"bd-2\"); exists != nil {\n    return fmt.Errorf(\"cannot rename: %s already exists\", \"bd-2\")\n}\nstore.UpdateIssueID(ctx, \"bd-1\", \"bd-2\", issue, actor)","handlingStrategy":"validation","validationCode":"func validateRename(ctx context.Context, store Store, oldID, newID string) error {\n    if newID == \"\" || strings.ContainsAny(newID, \" \\t/\") { return fmt.Errorf(\"invalid new id %q\", newID) }\n    if existing, _ := store.GetIssue(ctx, newID); existing != nil { return fmt.Errorf(\"id %s already exists\", newID) }\n    return nil\n}","typeGuard":null,"tryCatchPattern":"if err := store.UpdateIssueID(ctx, oldID, newID, issue, actor); err != nil {\n    if strings.Contains(err.Error(), \"update issue ID:\") {\n        var driverErr *SQLError // or driver-specific type\n        if errors.As(err, &driverErr) && isConstraintViolation(driverErr) {\n            return fmt.Errorf(\"target id %s conflicts with an existing row\", newID)\n        }\n    }\n    return err\n}","preventionTips":["Always check target ID uniqueness before renaming.","Enforce ID format validation (prefix + digits) in your tooling.","Retry failed renames in a fresh transaction; partial state is rolled back."],"tags":["database","sql","rename","constraint-violation"],"backgroundTag":"sql-constraint-violation","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}