gastownhall/beads · error
failed to link digest to root: %w
Error message
failed to link digest to root: %w
What it means
After creating the digest issue, squash links it to the molecule root via a DepParentChild dependency. If w.AddDependency fails, the error is wrapped as 'failed to link digest to root: %w'. The transaction aborts and all squash changes roll back.
Source
Thrown at cmd/bd/mol_squash.go:309
SquashedIDs: childIDs,
SquashedCount: len(children),
KeptChildren: keepChildren,
}
// Create digest issue
if err := w.CreateIssue(ctx, digestIssue, actorName); err != nil {
return nil, fmt.Errorf("failed to create digest issue: %w", err)
}
result.DigestID = digestIssue.ID
// Link digest to root as parent-child
dep := &types.Dependency{
IssueID: digestIssue.ID,
DependsOnID: root.ID,
Type: types.DepParentChild,
}
if err := w.AddDependency(ctx, dep, actorName); err != nil {
return nil, fmt.Errorf("failed to link digest to root: %w", err)
}
// Delete ephemeral children within the same transaction
if !keepChildren {
for _, id := range childIDs {
if err := w.DeleteIssue(ctx, id, actorName); err != nil {
return nil, fmt.Errorf("failed to delete child %s: %w", id, err)
}
result.DeletedCount++
}
}
// Auto-close the root if it's a wisp — squash completes the molecule lifecycle
if root.Ephemeral {
reason := fmt.Sprintf("Squashed: %d steps → digest %s", len(children), result.DigestID)
if err := w.CloseIssue(ctx, root.ID, reason, actorName); err != nil {
return nil, fmt.Errorf("failed to close wisp root %s: %w", root.ID, err)
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped cause to identify constraint vs storage failure
- Ensure no concurrent bd process is mutating the same molecule; retry after it finishes
- Verify the root issue still exists and the digest was created in the same transaction (it is, so suspect storage-level faults)
- Run bd doctor and retry once storage is healthy
Defensive patterns
Strategy: try-catch
Validate before calling
// Confirm root still exists immediately before squash
root, err := s.GetIssue(ctx, rootID)
if err != nil || root == nil {
return fmt.Errorf("root %s no longer exists", rootID)
} Try / catch
if err := squashAndReport(...); err != nil {
if strings.Contains(err.Error(), "failed to link digest to root") {
log.Printf("dependency link failed; squash rolled back: %v", errors.Unwrap(err))
}
return err
} Prevention
- Serialize molecule mutations through a single bd session
- Do not delete molecule roots while a squash is running
- Keep dependency schema current via bd doctor / migrations
When it happens
Trigger: bd mol squash when the parent-child dependency insert fails: dependency constraint violations, missing root/digest rows (deleted concurrently), storage write error, or database lock.
Common situations: Another process deleted the root between lookup and write; dependency table schema mismatch; DB locked by a concurrent squash or sync.
Related errors
- db: DependencySQLRepository.Insert: dep must not be nil
- db: DependencySQLRepository.Insert: IssueID must not be empt
- db: DependencySQLRepository.Insert: DependsOnID must not be
- db: DependencySQLRepository.ValidateBlockingHierarchy: dep m
- failed to create digest issue: %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/e84fbba4e16bdec9.
Report an issue: GitHub.