gastownhall/beads · error
db: DependencySQLRepository.Insert: mark is_blocked (affecte
Error message
db: DependencySQLRepository.Insert: mark is_blocked (affected): %w
What it means
This error wraps a failure from MarkIsBlockedInTx, the final propagation pass that marks all issues in the affected set as blocked after adding a scheduling (blocks/conditional/waits-for) edge. The edge exists but blocked-state propagation failed, leaving downstream issues potentially stale.
Source
Thrown at internal/storage/domain/db/dependency.go:222
}
if aerr != nil {
return fmt.Errorf("db: DependencySQLRepository.Insert: affected set: %w", aerr)
}
if dep.Type == types.DepBlocks || dep.Type == types.DepConditionalBlocks {
if err := r.markDirectBlockedSource(ctx, dep.IssueID, srcIsWisp, dep.DependsOnID, targetCol); err != nil {
return fmt.Errorf("db: DependencySQLRepository.Insert: mark is_blocked: %w", err)
}
affectedIssues, affectedWisps = issueops.RemoveSourceFromAffected(dep.IssueID, srcIsWisp, affectedIssues, affectedWisps)
}
if dep.Type == types.DepParentChild {
if err := issueops.RecomputeIsBlockedInTx(ctx, r.runner, affectedIssues, affectedWisps); err != nil {
return fmt.Errorf("db: DependencySQLRepository.Insert: recompute is_blocked: %w", err)
}
// Snapshot only after all derived blocked-state maintenance has completed.
return issueops.RecordDepEventInTx(ctx, r.runner, issueops.EventDepAdd, dep.IssueID, string(dep.Type), dep.DependsOnID, metadata, actor)
}
if err := issueops.MarkIsBlockedInTx(ctx, r.runner, affectedIssues, affectedWisps); err != nil {
return fmt.Errorf("db: DependencySQLRepository.Insert: mark is_blocked (affected): %w", err)
}
// Snapshot only after all derived blocked-state maintenance has completed.
// Never gated on opts.EmitEvent: a structurally-wired edge is as real to a
// replaying consumer as one added by an explicit dep verb.
return issueops.RecordDepEventInTx(ctx, r.runner, issueops.EventDepAdd, dep.IssueID, string(dep.Type), dep.DependsOnID, metadata, actor)
}
// classifyMissingEndpoint names the endpoint behind a foreign-key refusal,
// re-read on the same runner that refused the insert. The driver's message
// names its constraint, but taking identity out of driver prose is the thing a
// typed refusal exists to avoid, so the two endpoints are read back instead —
// only on the refusal path, so a bulk add still pays no probe per edge.
//
// The refusal is never downgraded to a probe's failure: anything the reads
// cannot settle returns nil and the caller keeps the original error.
func (r *dependencySQLRepositoryImpl) classifyMissingEndpoint(ctx context.Context, dep *types.Dependency, sourceIsWisp bool, targetCol string, insertErr error) error {
if !dberrors.IsMissingForeignKeyTarget(insertErr) {
return nilView on GitHub (pinned to 71377f2769)
Solutions
- Retry the operation; same-type inserts are idempotent.
- Run a blocked-state recompute/repair to clear stale flags.
- Verify schema version with bd doctor / migrate.
- Inspect the wrapped driver error for the failing statement.
Defensive patterns
Strategy: retry
Try / catch
if err := repo.Insert(ctx, dep, actor, opts); err != nil {
if strings.Contains(err.Error(), "mark is_blocked (affected)") {
// propagation failed; re-run Insert (idempotent) or run blocked-state repair
}
} Prevention
- Retry inserts on transient failure — same-type inserts are idempotent.
- Run scheduled is_blocked recomputes.
- Migrate schema before upgrading bd.
When it happens
Trigger: Calling Insert for a non-parent-child scheduling edge where issueops.MarkIsBlockedInTx fails on the affected set — driver error, connection loss, or schema mismatch during the bulk UPDATE.
Common situations: Connection dropped mid bulk-update; schema drift; very large affected sets timing out.
Related errors
- db: DependencySQLRepository.Insert: mark is_blocked: %w
- db: DependencySQLRepository.Insert: recompute is_blocked: %w
- recompute is_blocked after delete for %s: %w
- recompute is_blocked after batch delete: %w
- ErrTransaction
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/81002f0c295d9f85.
Report an issue: GitHub.