{"record":{"id":"cd0c5d9ac779f6e2","repo":"gastownhall/beads","slug":"delete-count-wisp-events-w","errorCode":null,"errorMessage":"delete: count wisp events: %w","messagePattern":"delete: count wisp events: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":139,"sourceCode":"\tresult.DependenciesCount = depCount\n\n\tlabelIssue, err := u.labelRepo.CountAllForIDs(ctx, regularIDs, LabelOpts{})\n\tif err != nil {\n\t\treturn DeleteIssuesResult{}, fmt.Errorf(\"delete: count labels: %w\", err)\n\t}\n\tlabelWisp, err := u.labelRepo.CountAllForIDs(ctx, wispIDs, LabelOpts{UseWispsTable: true})\n\tif err != nil {\n\t\treturn DeleteIssuesResult{}, fmt.Errorf(\"delete: count wisp labels: %w\", err)\n\t}\n\tresult.LabelsCount = labelIssue + labelWisp\n\n\tevIssue, err := u.eventsRepo.CountAllForIDs(ctx, regularIDs, RecordEventOpts{})\n\tif err != nil {\n\t\treturn DeleteIssuesResult{}, fmt.Errorf(\"delete: count events: %w\", err)\n\t}\n\tevWisp, err := u.eventsRepo.CountAllForIDs(ctx, wispIDs, RecordEventOpts{UseWispsTable: true})\n\tif err != nil {\n\t\treturn DeleteIssuesResult{}, fmt.Errorf(\"delete: count wisp events: %w\", err)\n\t}\n\tresult.EventsCount = evIssue + evWisp\n\n\tif params.DryRun {\n\t\tresult.DeletedCount = len(regularIDs) + len(wispIDs)\n\t\treturn result, nil\n\t}\n\n\tvar connected map[string]*types.Issue\n\tvar connectedIsWisp map[string]bool\n\tif params.UpdateTextReferences {\n\t\tdeletedSet := make(map[string]bool, len(allIDs))\n\t\tfor _, id := range allIDs {\n\t\t\tdeletedSet[id] = true\n\t\t}\n\t\tconnected, connectedIsWisp, err = u.collectConnectedIssues(ctx, allIDs, deletedSet)\n\t\tif err != nil {\n\t\t\treturn result, err","sourceCodeStart":121,"sourceCodeEnd":157,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L121-L157","documentation":"deleteMany wraps errors from eventsRepo.CountAllForIDs on the wisps table (UseWispsTable: true) while counting pre-delete events. The 'delete: count wisp events:' prefix identifies this step; the underlying error is preserved. Deletion has not begun.","triggerScenarios":"Any deleteMany path where CountAllForIDs(ctx, wispIDs, RecordEventOpts{UseWispsTable: true}) fails — wisp events table inaccessible, SQL error, or connection failure.","commonSituations":"Wisp-heavy deletes after schema changes to wisp event storage; Dolt unavailability during automated cleanup jobs; permission problems on the wisps table.","solutions":["Unwrap the error chain for the wisp-events query failure","Confirm the wisps table/schema matches the installed beads version (upgrade if needed)","Retry the delete — safe, nothing modified yet","Check Dolt connectivity and server logs"],"exampleFix":"// before\nres, err := uc.DeleteWisps(ctx, ids, actor)\nif err != nil { return err }\n// after\nif err != nil && strings.Contains(err.Error(), \"count wisp events\") {\n\t// pre-delete stats failed; no data changed — check wisp schema and retry\n\treturn err\n}","handlingStrategy":"retry","validationCode":"if err := pingDolt(ctx); err != nil {\n\treturn fmt.Errorf(\"storage unavailable: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"res, err := uc.DeleteWisps(ctx, ids, actor)\nif err != nil && strings.Contains(err.Error(), \"count wisp events\") {\n\t// wisp events count failed before deletion — check schema, then retry\n\treturn err\n}","preventionTips":["Keep beads and wisp-table schema in sync via upgrades","Verify Dolt health before automated wisp cleanup","Retry — no data has been touched at this stage"],"tags":["go","delete","wisp","events","count"],"backgroundTag":"storage-operation-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}