gastownhall/beads · error
node %q: updating metadata refs: %w
Error message
node %q: updating metadata refs: %w
What it means
The follow-up `tx.UpdateIssue` that writes merged metadata back onto the freshly created issue failed. This is a storage-layer write failure specific to the metadata-ref step, wrapped with the node key; the transaction rolls back all created nodes.
Source
Thrown at cmd/bd/graph_apply.go:985
for i, node := range plan.Nodes {
keyToID[node.Key] = issues[i].ID
}
// Resolve MetadataRefs now that all IDs are known.
for i, node := range plan.Nodes {
if len(node.MetadataRefs) == 0 {
continue
}
metaJSON, err := types.MergeMetadataRefs(issues[i].Metadata, node.MetadataRefs, keyToID)
if err != nil {
return fmt.Errorf("node %q: %w", node.Key, err)
}
updates := map[string]interface{}{
"metadata": metaJSON,
}
if err := tx.UpdateIssue(ctx, issues[i].ID, updates, actor); err != nil {
return fmt.Errorf("node %q: updating metadata refs: %w", node.Key, err)
}
}
parentDepPairs := graphApplyParentDepPairs(plan.Nodes, keyToID)
newSchedulingEdges := make([][2]string, 0, len(plan.Nodes)+len(plan.Edges))
if err := validateGraphApplyPlannedParentBlockingPaths(ctx, tx, plan, keyToID, parentDepPairs); err != nil {
return err
}
if err := validateGraphApplyPlannedBlockingCycles(ctx, tx, plan, keyToID); err != nil {
return err
}
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 parentDepPairs[graphApplyDepPairKey(fromID, toID)] && depType != types.DepParentChild {
return fmt.Errorf("edge %d %s->%s duplicates a parent-child relationship with dependency type %q", i, fromID, toID, depType)
}View on GitHub (pinned to 71377f2769)
Solutions
- Inspect the wrapped inner error for the storage cause.
- Check Dolt/server health and connectivity, then re-run the apply.
- Retry after resolving contention; the rollback makes re-application safe.
- If persistent, verify no other process holds locks on the database.
Defensive patterns
Strategy: retry
Try / catch
err := bd.GraphApply(ctx, plan)
if err != nil && strings.Contains(err.Error(), "updating metadata refs") {
// transaction rolled back; check storage health then retry
return retryWithBackoff(func() error { _, err := bd.GraphApply(ctx, plan); return err }, 3)
} Prevention
- Keep storage backend healthy; watch for connection drops mid-transaction.
- Avoid concurrent writers on the same issues during apply.
- Retry safely — rollback guarantees no partial state.
When it happens
Trigger: Driver/Dolt error during UpdateIssue: backend unavailable, row locked, I/O error, or the update payload rejected by the driver.
Common situations: Dolt server connection dropped mid-transaction; disk full; concurrent writer contending on the same issue row.
Related errors
- batch create: %w
- graph create: %w
- failed to clear ephemeral flag on root %s: %w
- applyGraph: node %q: updating metadata refs: %w
- line %d (%s): %w
AI-assisted analysis of gastownhall/beads@71377f2769 (2026-08-30).
Data as JSON: /api/errors/96140206e78491d2.
Report an issue: GitHub.