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

  1. Inspect the wrapped cause to identify constraint vs storage failure
  2. Ensure no concurrent bd process is mutating the same molecule; retry after it finishes
  3. Verify the root issue still exists and the digest was created in the same transaction (it is, so suspect storage-level faults)
  4. 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

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


AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30). Data as JSON: /api/errors/e84fbba4e16bdec9. Report an issue: GitHub.