{"record":{"id":"ad266a113145bf7a","repo":"gastownhall/beads","slug":"add-label-w","errorCode":null,"errorMessage":"add label: %w","messagePattern":"add label: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/labels.go","lineNumber":153,"sourceCode":"\t// Reject an over-length label up front. The INSERT IGNORE below would\n\t// otherwise silently truncate it to the VARCHAR(255) column, storing a label\n\t// the caller never sent; a typed ErrFieldTooLong is the clean rejection.\n\tif err := types.CheckFieldLen(\"label\", label); err != nil {\n\t\treturn err\n\t}\n\tif labelTable == \"\" || eventTable == \"\" {\n\t\tisWisp := IsActiveWispInTx(ctx, tx, issueID)\n\t\t_, lt, et, _ := WispTableRouting(isWisp)\n\t\tif labelTable == \"\" {\n\t\t\tlabelTable = lt\n\t\t}\n\t\tif eventTable == \"\" {\n\t\t\teventTable = et\n\t\t}\n\t}\n\t//nolint:gosec // G201: labelTable is from WispTableRouting (\"labels\" or \"wisp_labels\")\n\tif _, err := tx.ExecContext(ctx, fmt.Sprintf(`INSERT IGNORE INTO %s (issue_id, label) VALUES (?, ?)`, labelTable), issueID, label); err != nil {\n\t\treturn fmt.Errorf(\"add label: %w\", err)\n\t}\n\tcomment := \"Added label: \" + label\n\tif err := InsertDerivedEvent(ctx, tx, eventTable, AuxEvent{\n\t\tIssueID:   issueID,\n\t\tEventType: types.EventLabelAdded,\n\t\tActor:     actor,\n\t\tComment:   str(comment),\n\t}); err != nil {\n\t\treturn fmt.Errorf(\"add label: record event: %w\", err)\n\t}\n\t// A label is part of the bead snapshot, so a label write journals as an\n\t// update carrying the complete post-mutation set.\n\treturn RecordEventInTx(ctx, tx, EventUpdate, issueID, actor)\n}\n\n// RemoveLabelInTx removes a label from an issue and records an event within\n// an existing transaction. Automatically routes to wisp tables if the ID is\n// an active wisp.","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/labels.go#L135-L171","documentation":"AddLabelInTx returns this when the INSERT IGNORE of a label row into labels/wisp_labels fails at execution time. The library uses INSERT IGNORE so duplicate labels are idempotent; any error here is a real failure (constraint violation other than duplicates, missing table, connection error). An associated derived event and update journal entry are only written after this succeeds.","triggerScenarios":"Calling AddLabelInTx (via ApplyLabelPatch) when the INSERT fails: label table missing, foreign-key violation because the issue doesn't exist, or connection failure within the transaction.","commonSituations":"Adding a label to an already-deleted issue ID (FK violation); schema version missing wisp_labels; transaction aborted earlier by a prior error leaving the connection in a bad state.","solutions":["Verify the issue exists before adding the label","Run schema migrations to ensure label tables exist","Check the wrapped driver error for FK/constraint messages and correct the input data"],"exampleFix":null,"handlingStrategy":"validation","validationCode":"var n int\nif err := tx.QueryRow(`SELECT COUNT(*) FROM issues WHERE id = ?`, issueID).Scan(&n); err != nil || n == 0 {\n    return fmt.Errorf(\"issue %s does not exist; cannot add label\", issueID)\n}","typeGuard":null,"tryCatchPattern":"if err := issueops.AddLabelInTx(ctx, tx, issueID, label, actor); err != nil {\n    if strings.Contains(err.Error(), \"foreign key\") || strings.Contains(err.Error(), \"Duplicate\") {\n        // invalid issue or constraint issue: fix input, don't retry blindly\n    }\n    return err\n}","preventionTips":["Verify the issue exists before mutating its labels","Run migrations so labels/wisp_labels tables exist","Rely on INSERT IGNORE semantics for idempotent duplicate adds — only non-duplicate errors surface","Check wrapped errors for constraint names to identify data problems"],"tags":["database","sql","labels","insert"],"backgroundTag":"sql-insert-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}