{"record":{"id":"270f2bf236d77c30","repo":"gastownhall/beads","slug":"graph-dependency-cycle-would-be-created-s","errorCode":null,"errorMessage":"graph dependency cycle would be created: %s","messagePattern":"graph dependency cycle would be created: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"cmd/bd/graph_apply.go","lineNumber":1088,"sourceCode":"\t\t\t\t\t\tcontinue\n\t\t\t\t\t}\n\t\t\t\t\td, err := types.NewGraphNodeDependency(issues[i].ID, depType, dep.Target, keyToID)\n\t\t\t\t\tif err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"node %q: %w\", node.Key, err)\n\t\t\t\t\t}\n\t\t\t\t\tif err := tx.AddDependency(ctx, d, actor); err != nil {\n\t\t\t\t\t\treturn fmt.Errorf(\"node %q: adding dep to %q: %w\", node.Key, dep.Target, err)\n\t\t\t\t\t}\n\t\t\t\t\tif graphApplySchedulingDependencyType(d.Type) {\n\t\t\t\t\t\tnewSchedulingEdges = append(newSchedulingEdges, [2]string{d.IssueID, d.DependsOnID})\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\tif cyclePath, err := tx.CycleThroughEdges(ctx, newSchedulingEdges); err != nil {\n\t\t\treturn fmt.Errorf(\"final graph cycle check: %w\", err)\n\t\t} else if cyclePath != \"\" {\n\t\t\treturn fmt.Errorf(\"graph dependency cycle would be created: %s\", cyclePath)\n\t\t}\n\n\t\t// Apply deferred assignees.\n\t\tfor i, assignee := range pendingAssignees {\n\t\t\tupdates := map[string]interface{}{\n\t\t\t\t\"assignee\": assignee,\n\t\t\t}\n\t\t\tif err := tx.UpdateIssue(ctx, issues[i].ID, updates, actor); err != nil {\n\t\t\t\treturn fmt.Errorf(\"node %q: setting assignee: %w\", plan.Nodes[i].Key, err)\n\t\t\t}\n\t\t}\n\n\t\treturn nil\n\t}); err != nil {\n\t\treturn nil, err\n\t}\n\n\treturn &GraphApplyResult{IDs: keyToID}, nil","sourceCodeStart":1070,"sourceCodeEnd":1106,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/cmd/bd/graph_apply.go#L1070-L1106","documentation":"This is the deliberate rejection raised when the final cycle check finds that the newly added scheduling dependencies would form a cycle. The message includes cyclePath, the concrete chain of issues forming the loop, so the developer can see exactly which edges to break.","triggerScenarios":"tx.CycleThroughEdges returns a non-empty cyclePath after the plan's parent-child and scheduling edges are inserted — i.e. some combination of new edges closes a loop (A blocks B blocks ... blocks A).","commonSituations":"Hand-authored graphs where mutual blocks were specified, or a new edge that closes a loop through pre-existing dependencies in the database.","solutions":["Read cyclePath in the message to identify the loop's members","Remove or reverse one edge in the reported path","Change one edge to a non-scheduling type (not blocks) if a soft relation was intended","Run bd blocked / bd dep tree on the path members to understand pre-existing deps"],"exampleFix":"// before\n{\"from\":\"a\",\"to\":\"b\",\"type\":\"blocks\"},{\"from\":\"b\",\"to\":\"a\",\"type\":\"blocks\"}\n// after: drop the back edge\n{\"from\":\"a\",\"to\":\"b\",\"type\":\"blocks\"}","handlingStrategy":"validation","validationCode":"// topological check over plan edges plus existing DB deps\nif err := topoSort(planNodes, append(planEdges, existingDBDeps()...)); err != nil {\n  return fmt.Errorf(\"plan would create a cycle: %w\", err)\n}","typeGuard":"func acyclic(edges []Edge) bool { return topoSort(nodeKeys(edges), edges) == nil }","tryCatchPattern":"if err := bd.GraphApply(ctx, plan); err != nil {\n  if strings.Contains(err.Error(), \"cycle would be created\") {\n    path := extractCyclePath(err.Error())\n    plan = dropOneEdgeOnPath(plan, path)\n    return bd.GraphApply(ctx, plan)\n  }\n  return err\n}","preventionTips":["Run a topological sort on plan edges plus existing deps before applying","Never author mutual blocks between two nodes","Check bd dep tree for pre-existing deps that new edges might close loops with"],"tags":["beads","graph-apply","dependency-cycle","validation"],"backgroundTag":"dependency-cycle-detected","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}