gastownhall/beads · error
node %q: adding parent-child dep: %w
Error message
node %q: adding parent-child dep: %w
What it means
This error wraps a storage-layer failure that occurred while inserting the parent-child dependency for a node during `bd graph apply`. Every node that declares a parent gets a DepParentChild dependency written inside the apply transaction; if tx.AddDependency rejects it (e.g. the referenced parent ID does not exist or the storage layer errors), the whole apply transaction is aborted and the underlying reason is wrapped with the node key for identification.
Source
Thrown at cmd/bd/graph_apply.go:1025
}
// Add node parent-child dependencies first. The explicit and inline
// dependency sources below are also processed parent-first, so every
// blocking edge sees the plan's full hierarchy in storage.
for i, node := range plan.Nodes {
parentKey := node.effectiveParentKey()
parentID := node.ParentID
if parentKey != "" {
parentID = keyToID[parentKey]
}
if parentID != "" {
dep := &types.Dependency{
IssueID: issues[i].ID,
DependsOnID: parentID,
Type: types.DepParentChild,
}
if err := tx.AddDependency(ctx, dep, actor); err != nil {
return fmt.Errorf("node %q: adding parent-child dep: %w", node.Key, err)
}
newSchedulingEdges = append(newSchedulingEdges, [2]string{dep.IssueID, dep.DependsOnID})
}
}
for phase := 0; phase < 2; phase++ {
parentPhase := phase == 0
// Add explicit edges in stable order for this phase.
for i, edge := range plan.Edges {
fromID := resolveEdgeRef(edge.FromKey, edge.FromID, keyToID)
toID := resolveEdgeRef(edge.ToKey, edge.ToID, keyToID)
depType := graphApplyDependencyType(edge.Type)
if (depType == types.DepParentChild) != parentPhase {
continue
}
if parentDepPairs[graphApplyDepPairKey(fromID, toID)] {
if depType == types.DepParentChild {
continueView on GitHub (pinned to 71377f2769)
Solutions
- Verify every node's parent key exists in the plan's nodes section and resolves via keyToID
- Check the database still contains the parent issue (bd show <parent-id>) before applying
- Re-generate the graph plan from a fresh export so parent references match current IDs
- Inspect the wrapped underlying error for storage-specific causes (lock, connectivity)
Example fix
// before: plan references a parent key absent from the plan
{"key":"child","parent":"task-9"} // task-9 not in nodes
// after: ensure the parent node is declared in the same plan
{"key":"task-9",...},{"key":"child","parent":"task-9"} Defensive patterns
Strategy: validation
Validate before calling
for _, n := range plan.Nodes {
if n.Parent != "" && !keysInPlanOrDB(n.Parent) {
return fmt.Errorf("node %q: parent %q not found", n.Key, n.Parent)
}
} Type guard
func parentResolves(n Node, keyToID map[string]string) bool {
return n.Parent == "" || keyToID[n.Parent] != ""
} Try / catch
if err := bd.GraphApply(ctx, plan); err != nil {
var npe *NodeParentError
if errors.As(err, &npe) { /* fix plan parent refs */ }
return err
} Prevention
- Always declare parent nodes in the same plan before children reference them
- Regenerate plans from a fresh export rather than hand-editing IDs
- Run bd show on parent IDs before applying
When it happens
Trigger: Applying a graph plan where a node has a non-empty parentKey/ParentID and tx.AddDependency(ctx, dep, actor) returns an error — typically because the parent issue ID is not present in the database, a dependency constraint is violated, or the storage backend failed mid-transaction.
Common situations: Graph JSON files referencing parent keys that don't resolve to created issues, applying a plan against a database where the parent was deleted, or a corrupt/locked Dolt storage connection.
Related errors
- adding edge %s->%s: %w
- node %q: adding dep to %q: %w
- final graph cycle check: %w
- node %q: setting assignee: %w
- db: DependencySQLRepository.Insert: dep must not be nil
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/720380590996af47.
Report an issue: GitHub.