{"record":{"id":"2468edb9d11d7e46","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-insert-affected-set","errorCode":null,"errorMessage":"db: DependencySQLRepository.Insert: affected set: %w","messagePattern":"db: DependencySQLRepository\\.Insert: affected set: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":206,"sourceCode":"\n\t// is_blocked maintenance mirrors the classic AddDependencyInTx flow\n\t// (issueops/dependencies.go): the affected set expands the source by its\n\t// parent-child descendants (plus, for parent-child edges, waiters on the\n\t// target spawner), then a Mark pass propagates blocked state — or, for\n\t// parent-child adds (not monotonic: an already-closed child can satisfy an\n\t// any-children waits-for gate), a full mark/unmark Recompute. Skipping the\n\t// expansion left descendants stale when a blocking edge landed on their\n\t// ancestor (bd-6dnrw.44 item 3).\n\tsrcIsWisp := opts.UseWispsTable\n\tvar affectedIssues, affectedWisps []string\n\tvar aerr error\n\tif srcIsWisp {\n\t\taffectedIssues, affectedWisps, aerr = issueops.AffectedByDepChangeForWispInTx(ctx, r.runner, dep.IssueID, dep.DependsOnID, dep.Type)\n\t} else {\n\t\taffectedIssues, affectedWisps, aerr = issueops.AffectedByDepChangeInTx(ctx, r.runner, dep.IssueID, dep.DependsOnID, dep.Type)\n\t}\n\tif aerr != nil {\n\t\treturn fmt.Errorf(\"db: DependencySQLRepository.Insert: affected set: %w\", aerr)\n\t}\n\tif dep.Type == types.DepBlocks || dep.Type == types.DepConditionalBlocks {\n\t\tif err := r.markDirectBlockedSource(ctx, dep.IssueID, srcIsWisp, dep.DependsOnID, targetCol); err != nil {\n\t\t\treturn fmt.Errorf(\"db: DependencySQLRepository.Insert: mark is_blocked: %w\", err)\n\t\t}\n\t\taffectedIssues, affectedWisps = issueops.RemoveSourceFromAffected(dep.IssueID, srcIsWisp, affectedIssues, affectedWisps)\n\t}\n\tif dep.Type == types.DepParentChild {\n\t\tif err := issueops.RecomputeIsBlockedInTx(ctx, r.runner, affectedIssues, affectedWisps); err != nil {\n\t\t\treturn fmt.Errorf(\"db: DependencySQLRepository.Insert: recompute is_blocked: %w\", err)\n\t\t}\n\t\t// Snapshot only after all derived blocked-state maintenance has completed.\n\t\treturn issueops.RecordDepEventInTx(ctx, r.runner, issueops.EventDepAdd, dep.IssueID, string(dep.Type), dep.DependsOnID, metadata, actor)\n\t}\n\tif err := issueops.MarkIsBlockedInTx(ctx, r.runner, affectedIssues, affectedWisps); err != nil {\n\t\treturn fmt.Errorf(\"db: DependencySQLRepository.Insert: mark is_blocked (affected): %w\", err)\n\t}\n\t// Snapshot only after all derived blocked-state maintenance has completed.","sourceCodeStart":188,"sourceCodeEnd":224,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L188-L224","documentation":"This error wraps a failure from computing the set of issues affected by a dependency change (AffectedByDepChangeInTx / AffectedByDepChangeForWispInTx), which expands the source by parent-child descendants and waiters. This set drives is_blocked propagation, so the insert aborts before marking.","triggerScenarios":"Calling Insert where the affected-set query fails — recursive/descendant expansion query hits a driver error (connection loss, missing column, timeout on very deep hierarchies).","commonSituations":"Schema drift removing columns the affected-set query expects; timeouts on extremely deep parent-child trees; transient DB connection failures.","solutions":["Retry after confirming DB connectivity (transient failure).","Verify schema matches current beads version (bd doctor / migrate).","For very large hierarchies, check for query timeouts in the driver config.","Inspect the wrapped aerr for the failing query."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if err := repo.Insert(ctx, dep, actor, opts); err != nil {\n    if strings.Contains(err.Error(), \"affected set\") {\n        // transient traversal failure: backoff and retry, then run blocked-state repair\n    }\n}","preventionTips":["Keep parent-child hierarchies shallow where possible.","Run bd doctor to detect schema drift.","Retry transient DB failures with backoff."],"tags":["database","blocked-state","graph-traversal"],"backgroundTag":"dependency-affected-set-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}