{"record":{"id":"e67e49fa0d4043a4","repo":"gastownhall/beads","slug":"applygraph-edge-d-s-s-checking-planned-block","errorCode":null,"errorMessage":"applyGraph: edge %d %s->%s: checking planned blocking cycle: %w","messagePattern":"applyGraph: edge (.+?) (.+?)->(.+?): checking planned blocking cycle: %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/domain/issue.go","lineNumber":1481,"sourceCode":"\t\t\tcontinue\n\t\t}\n\t\tfromID := resolveEdgeRef(edge.FromKey, edge.FromID, keyToID)\n\t\ttoID := resolveEdgeRef(edge.ToKey, edge.ToID, keyToID)\n\t\tif fromID == \"\" || toID == \"\" {\n\t\t\tcontinue\n\t\t}\n\t\tif fromID == toID {\n\t\t\treturn fmt.Errorf(\"applyGraph: edge %d %s->%s creates a blocking dependency cycle\", i, fromID, toID)\n\t\t}\n\t\tadj[fromID] = append(adj[fromID], toID)\n\t\tchecks = append(checks, plannedEdge{index: i, fromID: fromID, toID: toID})\n\t}\n\n\tdepCache := make(map[string][]*types.Dependency)\n\tfor _, edge := range checks {\n\t\thasPath, err := u.graphHasPath(ctx, adj, depCache, edge.toID, edge.fromID, cycleRelevantDepType)\n\t\tif err != nil {\n\t\t\treturn fmt.Errorf(\"applyGraph: edge %d %s->%s: checking planned blocking cycle: %w\", edge.index, edge.fromID, edge.toID, err)\n\t\t}\n\t\tif hasPath {\n\t\t\treturn fmt.Errorf(\"applyGraph: edge %d %s->%s creates a blocking dependency cycle\", edge.index, edge.fromID, edge.toID)\n\t\t}\n\t}\n\treturn nil\n}\n\n// graphHasPath returns true if fromID can reach toID by following the\n// in-memory adjacency (planned parent-child + planned blocking edges) and\n// existing deps loaded lazily from the store. followExistingDep selects which\n// existing dep types the walk traverses, so callers can mirror either the\n// early blocking-only preflight or the broader ready-work graph. Per-node dep\n// fetches are cached so each visited node hits the DB at most once.\n//\n// Existing deps are loaded from BOTH dependency tables. The per-edge\n// depRepo.HasCycle probe this walk replaced traversed dependencies ∪\n// wisp_dependencies (and the embedded path's GetDependencyRecords selects the","sourceCodeStart":1463,"sourceCodeEnd":1499,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/domain/issue.go#L1463-L1499","documentation":"While checking whether a planned blocking edge would close a cycle, the helper graphHasPath returned an error; this wraps it with the edge's index and endpoints. The plan is rejected because cycle safety could not be verified — the cause is in the wrapped error (storage/query failure inside the path search).","triggerScenarios":"graphHasPath's dependency lookups (via depCache against depRepo) fail — Dolt query error, connectivity issue, or malformed dependency rows — while validating edge from->to for reachability toID->fromID.","commonSituations":"Database unavailable mid-validation; extremely deep/large graphs causing timeouts in the path search; inconsistent dep rows causing lookup errors.","solutions":["Inspect the wrapped error for the underlying query/storage cause.","Retry once the database is healthy.","Trim graph size or split the plan into smaller applies if the path search times out.","Validate existing dependency table consistency before applying."],"exampleFix":null,"handlingStrategy":"retry","validationCode":"// Local reachability pre-check mirrors the server-side check\nfor _, e := range plan.Edges {\n    if reachable(adj, e.To, e.From) {\n        return fmt.Errorf(\"edge %s->%s would close a cycle\", e.From, e.To)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err := bd.GraphApply(ctx, plan); err != nil {\n    if strings.Contains(err.Error(), \"checking planned blocking cycle\") {\n        // validation infrastructure failed, not the plan — retry after DB recovers\n        return retryWithBackoff(func() error { return bd.GraphApply(ctx, plan) })\n    }\n    return err\n}","preventionTips":["Verify DB health before large applies","Pre-compute cycles locally to reduce reliance on server-side path searches","Cache dep lookups when validating many edges"],"tags":["go","cycle-detection","storage","database"],"backgroundTag":"cycle-check-query-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}