{"record":{"id":"df93c0c898e7e6f4","repo":"gastownhall/beads","slug":"collectconnected-issues-w","errorCode":null,"errorMessage":"collectConnected (issues): %w","messagePattern":"collectConnected \\(issues\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue_delete.go","lineNumber":346,"sourceCode":"\tif err != nil {\n\t\treturn preview, err\n\t}\n\tpreview.ConnectedIssues = connected\n\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}","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue_delete.go#L328-L364","documentation":"This error wraps a failure from depRepo.ListByIssueIDs with Direction=DepDirectionBoth in collectConnectedIssues, which gathers both incoming and outgoing dependencies for the (expanded) id set to find connected issues surviving the delete. Called by both deleteMany (when UpdateTextReferences is set) and previewDelete; a failure propagates and aborts the whole operation.","triggerScenarios":"DeleteIssues/DeleteWisps with text-reference rewriting enabled, or PreviewDelete, when the bidirectional dependency query on the main table fails: DB outage, timeout on large allIDs sets, scan error.","commonSituations":"Large cascades making allIDs huge and the bulk query heavy; connection drops mid-delete (after rows were already removed — see partial-apply risk); lock contention on dependencies.","solutions":["Fix the wrapped driver-level error (connectivity, timeout, locks).","Retry the delete; dependency deletion by ID is idempotent, so re-runs are safe.","Chunk the delete when the cascade id set is very large.","Enable text-reference rewriting only when needed to skip this work path."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Check connectivity and bound the cascade before deleting with text rewriting:\nif err := store.PingContext(ctx); err != nil {\n    return fmt.Errorf(\"db unreachable: %w\", err)\n}\nif params.UpdateTextReferences && len(ids) > maxBatch {\n    return fmt.Errorf(\"delete batch too large for text rewriting: %d\", len(ids))\n}","typeGuard":"var dbErr *dberrors.DBError\nif errors.As(err, &dbErr) {\n    // classify driver failure before deciding retry vs abort\n}","tryCatchPattern":"res, err := uc.DeleteIssues(ctx, ids, opts)\nif err != nil && strings.Contains(err.Error(), \"collectConnected (issues)\") {\n    // deletes are idempotent by id; safe to retry after transient failure\n    return retryWithBackoff(func() error { _, e := uc.DeleteIssues(ctx, ids, opts); return e })\n}","preventionTips":["Keep delete batches small when UpdateTextReferences is enabled","Retry after transient failures — dependency deletes are idempotent","Increase timeouts for wide cascades","Disable text-reference rewriting when not needed"],"tags":["go","storage","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"}