{"record":{"id":"f25a374169ec3872","repo":"gastownhall/beads","slug":"db-dependencysqlrepository-insert-recompute-is-b","errorCode":null,"errorMessage":"db: DependencySQLRepository.Insert: recompute is_blocked: %w","messagePattern":"db: DependencySQLRepository\\.Insert: recompute is_blocked: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/db/dependency.go","lineNumber":216,"sourceCode":"\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.\n\t// Never gated on opts.EmitEvent: a structurally-wired edge is as real to a\n\t// replaying consumer as one added by an explicit dep verb.\n\treturn issueops.RecordDepEventInTx(ctx, r.runner, issueops.EventDepAdd, dep.IssueID, string(dep.Type), dep.DependsOnID, metadata, actor)\n}\n\n// classifyMissingEndpoint names the endpoint behind a foreign-key refusal,\n// re-read on the same runner that refused the insert. The driver's message\n// names its constraint, but taking identity out of driver prose is the thing a\n// typed refusal exists to avoid, so the two endpoints are read back instead —\n// only on the refusal path, so a bulk add still pays no probe per edge.","sourceCodeStart":198,"sourceCodeEnd":234,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/db/dependency.go#L198-L234","documentation":"This error wraps a failure from RecomputeIsBlockedInTx, the full mark/unmark recompute run after adding a parent-child dependency edge. Parent-child adds are not monotonic, so a full recompute of affected issues' blocked state is required; if it fails, the insert aborts here.","triggerScenarios":"Calling Insert with dep.Type = DepParentChild where issueops.RecomputeIsBlockedInTx fails on the computed affected set — driver error, timeout on large sets, or schema mismatch.","commonSituations":"Very large affected sets causing timeouts; schema drift; connection failure mid-recompute.","solutions":["Retry after confirming connectivity; Insert is idempotent for same-type edges.","Run a full blocked-state recompute/repair (bd doctor or equivalent) to fix partially applied state.","Verify schema matches the current version.","Inspect the wrapped driver error."],"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(), \"recompute is_blocked\") {\n        // schedule a full recompute to restore consistent blocked state\n    }\n}","preventionTips":["Avoid very wide parent-child trees that inflate affected sets.","Tune driver timeouts for bulk updates.","Keep schema current."],"tags":["database","is-blocked","parent-child","recompute"],"backgroundTag":"blocked-state-recompute-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}