{"record":{"id":"272a4810f9f9be38","repo":"gastownhall/beads","slug":"previewdelete-list-wisp-deps-w","errorCode":null,"errorMessage":"previewDelete: list wisp deps: %w","messagePattern":"previewDelete: list wisp deps: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":313,"sourceCode":"\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}\n\twispDepRes, err := u.depRepo.ListByIssueIDs(ctx, ids, DepListOpts{Direction: DepDirectionOut, UseWispsTable: true})\n\tif err != nil && !dberrors.IsTableNotExist(err) {\n\t\treturn preview, fmt.Errorf(\"previewDelete: list wisp deps: %w\", err)\n\t}\n\tfor id, deps := range wispDepRes.Outgoing {\n\t\tpreview.DepRecords[id] = append(preview.DepRecords[id], deps...)\n\t}\n\n\tallIDs, err := u.issueRepo.FindAllDependents(ctx, ids)\n\tif err != nil {\n\t\treturn preview, fmt.Errorf(\"previewDelete: cascade expansion: %w\", err)\n\t}\n\tdeletedSet := make(map[string]bool, len(allIDs))\n\tfor _, id := range allIDs {\n\t\tdeletedSet[id] = true\n\t}\n\tconnected, _, err := u.collectConnectedIssues(ctx, allIDs, deletedSet)\n\tif err != nil {\n\t\treturn preview, err\n\t}\n\tpreview.ConnectedIssues = connected","sourceCodeStart":295,"sourceCodeEnd":331,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L295-L331","documentation":"This error wraps a failure from depRepo.ListByIssueIDs with UseWispsTable=true and Direction=DepDirectionOut in previewDelete. Missing wisps tables are tolerated via dberrors.IsTableNotExist; other failures abort the preview.","triggerScenarios":"PreviewDelete/PreviewDeleteWisp when the wisps dependency table exists but the outgoing-dependency query fails for another reason: connection error, timeout, schema/scan mismatch.","commonSituations":"Concurrent wisp writes locking the table; upgrade left wisps schema inconsistent; DB outage during delete preview.","solutions":["Inspect the wrapped cause and address connectivity/timeout first.","Re-run the preview after transient failures.","Align the wisps schema via migrations if it diverged.","If wisps are unused, confirm the table-not-exist path is what's expected (it is skipped silently)."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Ensure wisps schema consistency before previewing wisp deletes:\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: wisps table absent\n}","tryCatchPattern":"preview, err := uc.PreviewDeleteWisp(ctx, ids)\nif err != nil && strings.Contains(err.Error(), \"previewDelete: list wisp deps\") {\n    if !dberrors.IsTableNotExist(errors.Unwrap(err)) {\n        return fmt.Errorf(\"wisp dependency lookup failed: %w\", err)\n    }\n}","preventionTips":["Align wisps schema via migrations after upgrades","Avoid concurrent wisp writes during previews","Retry transient DB failures","Check connectivity before bulk previews"],"tags":["go","storage","wisps","preview"],"backgroundTag":"dependency-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}