{"record":{"id":"8c83c72865e60546","repo":"gastownhall/beads","slug":"failed-to-record-event-w","errorCode":null,"errorMessage":"failed to record event: %w","messagePattern":"failed to record event: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/issueops/close.go","lineNumber":376,"sourceCode":"\t\t\treturn nil, fmt.Errorf(\"%w: issue %s\", storage.ErrNotFound, id)\n\t\t}\n\t\tif qerr != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to check issue existence: %w\", qerr)\n\t\t}\n\t\tif types.Status(status) == types.StatusClosed {\n\t\t\treturn &CloseResult{IsWisp: isWisp, AlreadyClosed: true}, nil\n\t\t}\n\t\treturn nil, fmt.Errorf(\"failed to close issue: %s\", id)\n\t}\n\n\t// A closed issue holds no lease (no-op for wisps, which are never leased).\n\tif err := DeleteLeaseInTx(ctx, tx, id); err != nil {\n\t\treturn nil, err\n\t}\n\n\tif recordEvent {\n\t\tif err := RecordEventInTable(ctx, tx, eventTable, id, types.EventClosed, actor, reason); err != nil {\n\t\t\treturn nil, fmt.Errorf(\"failed to record event: %w\", err)\n\t\t}\n\t}\n\n\trecompute, err := RecomputeIsBlockedInTxWithResult(ctx, tx, affectedIssues, affectedWisps)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"recompute is_blocked after close for %s: %w\", id, err)\n\t}\n\n\t// Snapshot only after all derived blocked-state maintenance has completed.\n\t// recordEvent gates the human audit event, never the journal.\n\tif err := RecordEventInTx(ctx, tx, EventClose, id, actor); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &CloseResult{IsWisp: isWisp, IssueRowsChanged: !isWisp || recompute.IssueRowsChanged}, nil\n}\n","sourceCodeStart":358,"sourceCodeEnd":393,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/issueops/close.go#L358-L393","documentation":"This error wraps a failure of RecordEventInTable when writing the 'closed' event to the event table after a successful close UPDATE. The issue row itself was closed, but the audit/journal event could not be recorded, so the whole transaction is rolled back and the close is reported as failed. The underlying event-write error is preserved via %w.","triggerScenarios":"RecordEventInTable errors while inserting into the events table inside the close transaction: missing events table, schema mismatch, constraint violation, connection loss, or context cancellation during the insert.","commonSituations":"Partial migrations leaving an outdated events table; disk-full or read-only database; actor or payload too long for a column; concurrent schema changes by another beads version.","solutions":["Inspect the wrapped driver error (errors.Is/As) for the specific insert failure (missing table, constraint, connection).","Run schema checks/migrations (bd doctor) to ensure the event table matches the binary version.","Retry the close in a fresh transaction once the database is writable and healthy.","Verify disk space and write permissions on the database backend."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"err := store.CloseIssue(ctx, id, actor, reason)\nif err != nil && strings.Contains(err.Error(), \"failed to record event\") {\n    // tx rolled back; safe to retry whole close\n    return retryClose(ctx, id, actor, reason, 1)\n}","preventionTips":["Run schema migrations so the events table matches the binary version.","Ensure the database is writable (disk space, permissions) before bulk closes.","Retry the full close — the transaction rollback leaves state consistent.","Watch for long actor/reason strings that could exceed column limits."],"tags":["database","event-log","transaction","sql"],"backgroundTag":"event-record-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}