gastownhall/beads · error

failed to delete child %s: %w

Error message

failed to delete child %s: %w

What it means

When keepChildren is false, squash deletes each ephemeral child issue inside the same transaction. A failed w.DeleteIssue is wrapped as 'failed to delete child %s: %w' with the child ID, and the entire squash rolls back.

Source

Thrown at cmd/bd/mol_squash.go:316

		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)
		}
		// Clear ephemeral so the closed root stops being re-emitted by every wisp-table export cycle.
		if err := w.UpdateIssue(ctx, root.ID, map[string]interface{}{"wisp": false}, actorName); err != nil {
			return nil, fmt.Errorf("failed to clear ephemeral flag on root %s: %w", root.ID, err)
		}
		result.WispSquash = true
	}

View on GitHub (pinned to 71377f2769)

Solutions

  1. Read the wrapped cause and child ID; check for external dependencies blocking deletion
  2. Remove or re-point dependencies that reference the child, or use --keep-children to skip deletion
  3. Ensure no concurrent bd process is running against the same database
  4. Retry after resolving storage constraints (writability, disk space)

Example fix

// before: squash fails outright
bd mol squash <root>
// after: keep children when deletion is blocked
bd mol squash <root> --keep-children
Defensive patterns

Strategy: fallback

Validate before calling

// Detect external dependencies on children before non-keeping squash
for _, id := range childIDs {
    if deps, _ := s.GetDependencies(ctx, id); len(deps) > 0 {
        // surface or switch to --keep-children
    }
}

Try / catch

err := squashMolecule(ctx, s, root, children, false, summary, actor)
if err != nil && strings.Contains(err.Error(), "failed to delete child") {
    // fallback: retry with keepChildren=true
    return squashMolecule(ctx, s, root, children, true, summary, actor)
}

Prevention

When it happens

Trigger: bd mol squash (without --keep-children) when deleting a child fails: foreign-key/dependency constraints referencing the child, storage write error, or database locked mid-transaction.

Common situations: Child still referenced by dependencies from outside the molecule; concurrent writer holding the lock; read-only filesystem or disk full.

Related errors


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