{"record":{"id":"f5ebe26a751eee41","repo":"gastownhall/beads","slug":"applygraph-edge-d-s-s-w","errorCode":null,"errorMessage":"applyGraph: edge %d (%s -> %s): %w","messagePattern":"applyGraph: edge (.+?) \\((.+?) -> (.+?)\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1264,"sourceCode":"\t\t\t\tcontinue\n\t\t\t}\n\n\t\t\tif parentDepPairs[depPairKey(fromID, toID)] {\n\t\t\t\tif depType == types.DepParentChild {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: edge %d %s->%s duplicates a parent-child relationship with dependency type %q\", i, fromID, toID, depType)\n\t\t\t}\n\t\t\tif parentDepPairs[depPairKey(toID, fromID)] && cycleRelevantDepType(depType) {\n\t\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: edge %d %s->%s creates a blocking reverse of a parent-child relationship\", i, fromID, toID)\n\t\t\t}\n\n\t\t\tdep, err := types.NewGraphEdgeDependency(fromID, toID, depType, edge.Gate, edge.SpawnerKey, edge.SpawnerID, edge.ThreadID, keyToID)\n\t\t\tif err != nil {\n\t\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: edge %d: %w\", i, err)\n\t\t\t}\n\t\t\tif err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: useWisp}); err != nil {\n\t\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: edge %d (%s -> %s): %w\", i, fromID, toID, err)\n\t\t\t}\n\t\t\tif types.IsSchedulingEdge(depType) {\n\t\t\t\tnewSchedulingEdges = append(newSchedulingEdges, [2]string{fromID, toID})\n\t\t\t}\n\t\t}\n\n\t\t// Per-node inline deps in stable order for this phase, resolved by the\n\t\t// same shared builder as the embedded executeGraphApply (cmd/bd/graph_apply.go).\n\t\tfor _, node := range plan.Nodes {\n\t\t\tfor _, nd := range node.Deps {\n\t\t\t\tdep, err := types.NewGraphNodeDependency(keyToID[node.Key], nd.Type, nd.Target, keyToID)\n\t\t\t\tif err != nil {\n\t\t\t\t\treturn GraphApplyResult{}, fmt.Errorf(\"applyGraph: node %q: %w\", node.Key, err)\n\t\t\t\t}\n\t\t\t\tif (dep.Type == types.DepParentChild) != parentPhase {\n\t\t\t\t\tcontinue\n\t\t\t\t}\n\t\t\t\tif err := u.depRepo.Insert(ctx, dep, actor, DepInsertOpts{UseWispsTable: useWisp}); err != nil {","sourceCodeStart":1246,"sourceCodeEnd":1282,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1246-L1282","documentation":"applyGraph applies a dependency-graph plan and wraps any failure from inserting an edge (dependency) between two issues with the edge index and its from/to issue IDs. This error means the depRepo.Insert call for one edge failed — the edge was constructed fine, but persisting it into the dependencies table (or wisps table) returned an error. The underlying wrapped error carries the real cause (constraint violation, missing issue, storage failure).","triggerScenarios":"Calling bd graph apply (or the embedded applyGraph path) with a plan whose edges reference issues where the Insert violates constraints: target issue not found in the same table (issues vs wisps mismatch when useWisp is wrong), a duplicate dependency edge, or an underlying Dolt/storage error during Insert.","commonSituations":"Applying a plan generated against a different database state (edges pointing at issues that were deleted or not created in an earlier phase); mixed wisp/non-wisp nodes where the UseWispsTable flag doesn't match where both endpoints live; network/DB failures during a large apply; re-applying a plan that already inserted the edge under a unique constraint.","solutions":["Read the wrapped %w error to identify the root cause (not-found vs constraint vs storage).","Verify every edge endpoint key exists in the plan's nodes and was created in an earlier phase before edges are applied.","Ensure the plan's wisp/non-wisp flag matches the actual target table for both endpoints (check UseWispsTable handling).","If re-applying, make the plan idempotent or clear already-applied edges first.","Retry after resolving transient Dolt/storage connectivity errors."],"exampleFix":"// before: edge references a key absent from the plan's created nodes\n{\"edges\": [{\"fromKey\": \"bd-99\", \"toKey\": \"bd-100\", \"type\": \"blocks\"}]}\n// after: ensure bd-99/bd-100 are defined as nodes in the same plan or already exist\n{\"nodes\": [{\"key\": \"bd-99\"}, {\"key\": \"bd-100\"}], \"edges\": [{\"fromKey\": \"bd-99\", \"toKey\": \"bd-100\", \"type\": \"blocks\"}]}","handlingStrategy":"validation","validationCode":"// Pre-check: every edge endpoint must exist (or be a plan node) before apply\nfor _, e := range plan.Edges {\n    if !keysInPlanOrDB(e.FromKey) || !keysInPlanOrDB(e.ToKey) {\n        return fmt.Errorf(\"edge %s->%s references unknown issue\", e.FromKey, e.ToKey)\n    }\n}","typeGuard":"func edgeEndpointsResolved(e Edge, keyToID map[string]string) bool {\n    return resolveEdgeRef(e.FromKey, e.FromID, keyToID) != \"\" &&\n        resolveEdgeRef(e.ToKey, e.ToID, keyToID) != \"\"\n}","tryCatchPattern":"if err := bd.GraphApply(ctx, plan); err != nil {\n    var edgeErr *graphEdgeError\n    if errors.As(err, &edgeErr) {\n        log.Printf(\"edge %d (%s -> %s) failed: %v\", edgeErr.Index, edgeErr.From, edgeErr.To, errors.Unwrap(err))\n    }\n    return err\n}","preventionTips":["Validate all edge endpoint keys against plan nodes plus existing issues before apply","Keep wisp/non-wisp usage consistent between nodes and edges","Make plans idempotent to survive re-application","Check database connectivity before large applies"],"tags":["go","storage","dependency-graph","apply"],"backgroundTag":"graph-edge-insert-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}