{"record":{"id":"a44896bf8e95f634","repo":"gastownhall/beads","slug":"collectconnected-wisps-w","errorCode":null,"errorMessage":"collectConnected (wisps): %w","messagePattern":"collectConnected \\(wisps\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":350,"sourceCode":"\treturn preview, nil\n}\n\nfunc (u *issueUseCaseImpl) collectConnectedIssues(\n\tctx context.Context, allIDs []string, deletedSet map[string]bool,\n) (map[string]*types.Issue, map[string]bool, error) {\n\tout := map[string]*types.Issue{}\n\tisWisp := map[string]bool{}\n\tif len(allIDs) == 0 {\n\t\treturn out, isWisp, nil\n\t}\n\n\tissueRes, err := u.depRepo.ListByIssueIDs(ctx, allIDs, DepListOpts{Direction: DepDirectionBoth})\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"collectConnected (issues): %w\", err)\n\t}\n\twispRes, err := u.depRepo.ListByIssueIDs(ctx, allIDs, DepListOpts{Direction: DepDirectionBoth, UseWispsTable: true})\n\tif err != nil && !dberrors.IsTableNotExist(err) {\n\t\treturn nil, nil, fmt.Errorf(\"collectConnected (wisps): %w\", err)\n\t}\n\n\tneighbors := map[string]bool{}\n\taccumulate := func(m map[string][]*types.Dependency) {\n\t\tfor _, deps := range m {\n\t\t\tfor _, d := range deps {\n\t\t\t\tfor _, candidate := range [2]string{d.IssueID, d.DependsOnID} {\n\t\t\t\t\tif candidate == \"\" || deletedSet[candidate] {\n\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\tneighbors[candidate] = true\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\taccumulate(issueRes.Outgoing)\n\taccumulate(issueRes.Incoming)\n\taccumulate(wispRes.Outgoing)","sourceCodeStart":332,"sourceCodeEnd":368,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L332-L368","documentation":"This error wraps a failure from depRepo.ListByIssueIDs with UseWispsTable=true and Direction=DepDirectionBoth in collectConnectedIssues. A missing wisps table is tolerated (IsTableNotExist short-circuits); any other failure aborts the delete or preview, since connected-issue detection would be incomplete.","triggerScenarios":"deleteMany (with text-reference rewriting) or previewDelete when the wisps dependency table exists but the bidirectional query fails: connection loss, timeout, schema/scan mismatch.","commonSituations":"Wisp table locked by concurrent writers; upgrade-related schema drift; transient DB failures during large cascade operations.","solutions":["Resolve the wrapped driver error first (connectivity, locks, timeouts).","Retry the operation; reads are safe and deletes are idempotent per ID.","Run migrations if the wisps schema drifted from the installed version.","If wisps are unused, the expected table-not-exist path is skipped silently — a surfaced error means something else failed."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Ensure wisps schema is migrated or intentionally absent before 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: no wisps dependency table\n}\nvar dbErr *dberrors.DBError\nif errors.As(err, &dbErr) {\n    // real driver failure — handle or propagate\n}","tryCatchPattern":"res, err := uc.DeleteWisps(ctx, ids, opts)\nif err != nil && strings.Contains(err.Error(), \"collectConnected (wisps)\") {\n    if !dberrors.IsTableNotExist(errors.Unwrap(err)) {\n        return fmt.Errorf(\"wisp connectivity scan failed: %w\", err)\n    }\n}","preventionTips":["Run migrations so wisps schema matches the binary","Distinguish tolerated IsTableNotExist from real failures","Retry transient failures — deletes are idempotent per ID","Avoid concurrent wisp writers during large deletes"],"tags":["go","storage","wisps","dependencies","connected-issues"],"backgroundTag":"dependency-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}