gastownhall/beads · error
add deps[%d]: insert: %w
Error message
add deps[%d]: insert: %w
What it means
When inserting an individual dependency edge fails, AddDependencies wraps it with 'insert: %w'. Typed failures — *DependencyHierarchyConflictError and *DependencyEndpointNotFoundError — are returned unwrapped so callers can errors.As them; everything else (e.g. constraint violations, storage errors) gets this wrapper. It means the edge write itself was rejected or failed.
Source
Thrown at internal/storage/domain/dependency.go:762
// create-with-deps, which calls depRepo.Insert directly without
// EmitEvent. UseWispsTable routes both the edge and that event to
// the source's own pair of tables.
_, sourceIsWisp := wispSources[dep.IssueID]
if err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{
UseWispsTable: sourceIsWisp,
HierarchyValidated: true,
CycleValidated: true,
EmitEvent: true,
}); err != nil {
var hierarchyConflict *DependencyHierarchyConflictError
if errors.As(err, &hierarchyConflict) {
return BulkAddDepsResult{}, err
}
var missingEndpoint *DependencyEndpointNotFoundError
if errors.As(err, &missingEndpoint) {
return BulkAddDepsResult{}, err
}
return BulkAddDepsResult{}, fmt.Errorf("add deps[%d]: insert: %w", i, err)
}
}
}
var pairs [][2]string
for _, dep := range deps {
if !types.IsSchedulingEdge(dep.Type) {
continue
}
pairs = append(pairs, [2]string{dep.IssueID, dep.DependsOnID})
}
if len(pairs) > 0 {
cyclePath, err := u.depRepo.CycleThroughEdges(ctx, pairs)
if err != nil {
return BulkAddDepsResult{}, fmt.Errorf("add deps: final cycle check: %w", err)
}
if cyclePath != "" {
return BulkAddDepsResult{}, cycleErrorf("add deps: dependency cycle would be created: %s", cyclePath)
}View on GitHub (pinned to 71377f2769)
Solutions
- Read the wrapped error after 'insert:' for the driver-level cause
- Re-check that both endpoint issues still exist before retrying
- If duplicates are expected, filter existing edges before the batch or tolerate the error per-edge
Defensive patterns
Strategy: try-catch
Validate before calling
// ensure both endpoints exist before the call
for _, d := range deps {
if _, err := issueRepo.Get(ctx, d.IssueID); err != nil { return err }
if _, err := issueRepo.Get(ctx, d.DependsOnID); err != nil { return err }
} Type guard
var miss *domain.DependencyEndpointNotFoundError
if errors.As(err, &miss) { /* handle missing endpoint typed path */ } Try / catch
if err != nil {
var hc *domain.DependencyHierarchyConflictError
var me *domain.DependencyEndpointNotFoundError
if errors.As(err, &hc) || errors.As(err, &me) { return err } // typed, unwrapped
// 'insert:' wrapper — driver/constraint issue; inspect wrapped cause
} Prevention
- Serialize concurrent writers that may insert the same edge
- Ensure endpoints exist and were not deleted mid-batch
- Check disk space / read-only filesystem before large writes
When it happens
Trigger: Calling AddDependencies where the per-edge repository insert returns a non-typed error — duplicate-edge constraint violations, storage write failures, or other driver errors not classified as hierarchy-conflict or missing-endpoint.
Common situations: Concurrent writers inserting the same edge; database read-only or disk full; referential issues when one endpoint was deleted between validation and insert.
Related errors
- loading deps for %s: %w
- failed to remove relates-to %s -> %s: %w
- failed to get dependencies for %s: %w
- failed to seed issue_counter for prefix %q at %d: %w
- failed to insert initial issue counter for prefix %q: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/5b7996d33bbd8dd4.
Report an issue: GitHub.