{"record":{"id":"d7f974b917b05190","repo":"gastownhall/beads","slug":"applygraph-node-q-parent-child-dep-s-s-w","errorCode":null,"errorMessage":"applyGraph: node %q: parent-child dep %s->%s: %w","messagePattern":"applyGraph: node %q: parent-child dep (.+?)->(.+?): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1215,"sourceCode":"\t// Pass 3 — insert node parent-child deps now that all IDs are known. These\n\t// must be visible before any blocking edge in the same plan so the storage\n\t// hierarchy guard evaluates existing + planned ancestry.\n\tfor _, node := range plan.Nodes {\n\t\tparentID := node.ParentID\n\t\tif node.ParentKey != \"\" {\n\t\t\tparentID = keyToID[node.ParentKey]\n\t\t}\n\t\tif parentID == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tchildID := keyToID[node.Key]\n\t\tdep := &types.Dependency{\n\t\t\tIssueID:     childID,\n\t\t\tDependsOnID: parentID,\n\t\t\tType:        types.DepParentChild,\n\t\t}\n\t\tif err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: useWisp}); err != nil {\n\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: node %q: parent-child dep %s->%s: %w\", node.Key, childID, parentID, err)\n\t\t}\n\t\tnewSchedulingEdges = append(newSchedulingEdges, [2]string{childID, parentID})\n\t}\n\n\t// Pass 4 — insert explicit edge deps in two stable phases: all additional\n\t// parent-child edges first, then every other type. Deduplicate against the\n\t// node parent-child pairs:\n\t//   - Same pair, parent-child type → skip (pass 3 already inserted it).\n\t//   - Same pair, different type   → error (conflicting edge over a parent-child link).\n\t//   - Reverse pair, blocking type → error (creates a parent → child blocking cycle).\n\t//\n\t// The blocking-only whole-graph preflight above gives early, edge-specific\n\t// errors. Repository Insert remains the defensive authority for the broader\n\t// blocks + conditional-blocks + parent-child scheduling graph.\n\tfor phase := 0; phase < 2; phase++ {\n\t\tparentPhase := phase == 0\n\t\tfor i, edge := range plan.Edges {\n\t\t\tfromID := resolveEdgeRef(edge.FromKey, edge.FromID, keyToID)","sourceCodeStart":1197,"sourceCodeEnd":1233,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1197-L1233","documentation":"Pass 3 of applyGraph inserts the implicit parent-child dependency rows for each node with a parent. If the dependency repository Insert fails (storage error, constraint violation, connection loss), the error is wrapped with this message identifying the node key and child->parent pair, and the whole apply aborts.","triggerScenarios":"u.depRepo.Insert returns an error while writing a DepParentChild row: DB locked/unreachable, duplicate dependency row already exists, wisps-table flag mismatch, or driver-level failure.","commonSituations":"Dolt server down mid-apply; leftover parent-child dep from a partially applied earlier plan; permission/schema issues after a beads version upgrade; disk full.","solutions":["Read the wrapped cause (%w) and address the underlying storage error (restart Dolt, check connectivity)","Remove the pre-existing duplicate dependency (bd dep remove child --depends-on parent) and re-apply","Re-run applyGraph with an idempotent/rebuilt plan; the pre-write passes should now dedupe","Check schema version compatibility after upgrading beads (bd migrate/doctor)"],"exampleFix":"// before\n// applyGraph fails: insert conflicts with existing row\n// after\n// delete the stale dep first:\n//   bd dep remove bd-2 --depends-on bd-1\n// then re-run applyGraph with the same plan","handlingStrategy":"try-catch","validationCode":"// Pre-check for an existing parent-child dep to avoid insert conflicts:\nfor _, n := range plan.Nodes {\n    if n.Parent != \"\" && depExists(n.Key, n.Parent) {\n        return fmt.Errorf(\"dep %s->%s already exists\", n.Key, n.Parent)\n    }\n}","typeGuard":null,"tryCatchPattern":"res, err := applyGraph(ctx, plan)\nif err != nil {\n    var wrapped string = err.Error()\n    if strings.Contains(wrapped, \"parent-child dep\") {\n        // inspect %w cause: storage down? duplicate row? retry after cleanup\n        log.Printf(\"graph apply failed on parent-child insert: %v\", err)\n    }\n    return err\n}","preventionTips":["Ensure the storage backend (Dolt server) is healthy before large applies","Clean partial state from failed applies before retrying","Keep beads and driver versions in sync","Monitor disk space and DB locks in CI runners"],"tags":["graph-apply","insert-failure","storage"],"backgroundTag":"dependency-insert-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}