{"record":{"id":"59e5007bc6a4234b","repo":"gastownhall/beads","slug":"applygraph-node-q-updating-metadata-refs-w","errorCode":null,"errorMessage":"applyGraph: node %q: updating metadata refs: %w","messagePattern":"applyGraph: node %q: updating metadata refs: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1157,"sourceCode":"\t\t}\n\t\tkeyToID[node.Key] = r.Issue.ID\n\t}\n\n\t// Pass 2 — resolve MetadataRefs now that every node has a minted ID.\n\t// Merges the resolved IDs into the issue's existing metadata JSON and\n\t// writes the result back via Update. Kept inside applyGraph so the CLI\n\t// cannot bypass this step; the proxied caller used to do it post-call.\n\tfor _, node := range plan.Nodes {\n\t\tif len(node.MetadataRefs) == 0 {\n\t\t\tcontinue\n\t\t}\n\t\tmetaJSON, err := types.MergeMetadataRefs(node.Issue.Metadata, node.MetadataRefs, keyToID)\n\t\tif err != nil {\n\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: node %q: %w\", node.Key, err)\n\t\t}\n\t\tupdates := map[string]any{\"metadata\": metaJSON}\n\t\tif err := u.issueRepo.Update(ctx, keyToID[node.Key], updates, actor, IssueTableOpts{UseWispsTable: useWisp}); err != nil {\n\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: node %q: updating metadata refs: %w\", node.Key, err)\n\t\t}\n\t}\n\n\t// Build the (childID, parentID) pair set and validate that any planned\n\t// parent-child link does not close a cycle through planned edges or\n\t// already-existing dependencies in the store. This must run before any\n\t// dep inserts to catch the violation before we've written anything.\n\tparentDepPairs := graphParentDepPairs(plan.Nodes, keyToID)\n\tnewSchedulingEdges := make([][2]string, 0, len(plan.Nodes)+len(plan.Edges))\n\tif err := u.validatePlannedBlockingPaths(ctx, plan, keyToID, parentDepPairs); err != nil {\n\t\treturn GraphApplyResult{}, err\n\t}\n\tif err := u.validatePlannedBlockingCycles(ctx, plan, keyToID); err != nil {\n\t\treturn GraphApplyResult{}, err\n\t}\n\t// Preserve failure-before-write for explicit edges that conflict directly\n\t// with an implicit node parent relationship. Parent-first mutation below is\n\t// for transitive hierarchy visibility, not for deferring structural errors.","sourceCodeStart":1139,"sourceCodeEnd":1175,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1139-L1175","documentation":"Wraps a failure from issueRepo.Update when persisting a node's merged metadata JSON back to the store during applyGraph pass 2. The refs were resolved successfully but the metadata update write failed. This is a storage-layer error: record not found, constraint violation, or driver/connection failure.","triggerScenarios":"Calling ApplyGraph where issueRepo.Update (writing {\"metadata\": metaJSON}) fails for a node — issue row missing, table tier mismatch, or DB error.","commonSituations":"Issue deleted between create and update phases; wisp/durable routing mismatch; transient Dolt/storage failure; schema drift on the metadata column.","solutions":["Check the wrapped inner error for the driver-level cause","Verify keyToID[node.Key] resolved to a real persisted issue ID","Confirm the update uses the same wisp tier (UseWispsTable) as the create pass","Retry transient failures; verify schema/migrations if persistent"],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// verify nodes exist before pass-2 update happens implicitly; for manual retries:\nfor _, n := range plan.Nodes {\n    if _, err := uc.GetIssue(ctx, keyToID[n.Key]); err != nil {\n        return fmt.Errorf(\"node %q issue %s not persisted\", n.Key, keyToID[n.Key])\n    }\n}","typeGuard":null,"tryCatchPattern":"result, err := uc.ApplyGraph(ctx, plan, actor)\nif err != nil && strings.Contains(err.Error(), \"updating metadata refs\") {\n    if isTransientStorageError(err) {\n        time.Sleep(backoff)\n        result, err = uc.ApplyGraph(ctx, plan, actor) // must be idempotent\n    }\n}","preventionTips":["Retry apply only if idempotent (nodes check existence)","Keep wisp routing consistent between create and update passes","Watch driver health/logs for transient Dolt failures","Avoid concurrent writes to the same issues during apply"],"tags":["graph-apply","metadata","update","storage"],"backgroundTag":"metadata-update-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}