{"record":{"id":"f40eaf08acb32e80","repo":"gastownhall/beads","slug":"previewdelete-load-wisps-w","errorCode":null,"errorMessage":"previewDelete: load wisps: %w","messagePattern":"previewDelete: load wisps: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":292,"sourceCode":"\tpreview := DeletePreview{\n\t\tIssues:          map[string]*types.Issue{},\n\t\tConnectedIssues: map[string]*types.Issue{},\n\t\tDepRecords:      map[string][]*types.Dependency{},\n\t}\n\tif len(ids) == 0 {\n\t\treturn preview, nil\n\t}\n\n\tfromIssues, err := u.issueRepo.GetByIDs(ctx, ids, IssueTableOpts{})\n\tif err != nil {\n\t\treturn preview, fmt.Errorf(\"previewDelete: load issues: %w\", err)\n\t}\n\tfor _, iss := range fromIssues {\n\t\tpreview.Issues[iss.ID] = iss\n\t}\n\tfromWisps, err := u.issueRepo.GetByIDs(ctx, ids, IssueTableOpts{UseWispsTable: true})\n\tif err != nil && !dberrors.IsTableNotExist(err) {\n\t\treturn preview, fmt.Errorf(\"previewDelete: load wisps: %w\", err)\n\t}\n\tfor _, iss := range fromWisps {\n\t\tpreview.Issues[iss.ID] = iss\n\t}\n\n\tfor _, id := range ids {\n\t\tif _, ok := preview.Issues[id]; !ok {\n\t\t\tpreview.NotFound = append(preview.NotFound, id)\n\t\t}\n\t}\n\n\tdepRes, err := u.depRepo.ListByIssueIDs(ctx, ids, DepListOpts{Direction: DepDirectionOut})\n\tif err != nil {\n\t\treturn preview, fmt.Errorf(\"previewDelete: list deps: %w\", err)\n\t}\n\tfor id, deps := range depRes.Outgoing {\n\t\tpreview.DepRecords[id] = deps\n\t}","sourceCodeStart":274,"sourceCodeEnd":310,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L274-L310","documentation":"This error wraps a failure from issueRepo.GetByIDs with UseWispsTable=true in previewDelete. A missing wisps table is deliberately tolerated (IsTableNotExist is ignored) because a database may never have contained wisps; any other failure aborts the preview.","triggerScenarios":"PreviewDelete/PreviewDeleteWisp when the wisps table exists but the bulk fetch of wisp rows by id fails for a non-table-not-exist reason: connection drop, timeout, scan error.","commonSituations":"Wisps table locked by another writer; driver/schema drift after an upgrade; transient DB outage during a delete dry-run.","solutions":["Check the wrapped cause; if it is table-not-exist the code already tolerates it, so a surfaced error means a different failure.","Restore DB connectivity and re-run the preview.","Verify wisps-table schema matches the installed beads version.","Chunk very large id lists."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Ensure wisps schema is present or intentionally absent:\nif err := migrate(ctx); err != nil {\n    return fmt.Errorf(\"wisps schema check failed: %w\", err)\n}","typeGuard":"if dberrors.IsTableNotExist(errors.Unwrap(err)) {\n    return nil // tolerated: no wisps in this database\n}\nvar dbErr *dberrors.DBError\nif errors.As(err, &dbErr) {\n    // real driver failure\n}","tryCatchPattern":"preview, err := uc.PreviewDeleteWisp(ctx, ids)\nif err != nil && strings.Contains(err.Error(), \"previewDelete: load wisps\") {\n    if !dberrors.IsTableNotExist(errors.Unwrap(err)) {\n        return fmt.Errorf(\"wisp preview failed: %w\", err)\n    }\n}","preventionTips":["Keep wisps tables migrated or confirm wisps are unused","Retry transient failures — preview is read-only","Avoid concurrent wisp writers during previews","Chunk oversized id lists"],"tags":["go","storage","wisps","preview"],"backgroundTag":"issue-load-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}