{"record":{"id":"1d2b65f2239e895e","repo":"gastownhall/beads","slug":"final-cycle-check-failed-no-edges-added-w-1d2b65","errorCode":null,"errorMessage":"final cycle check failed (no edges added): %w","messagePattern":"final cycle check failed \\(no edges added\\): %w","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/storage/uow/batch_applier.go","lineNumber":510,"sourceCode":"}\n\n// runEndGate re-validates the graph the WHOLE request produced, through the\n// same two repository checks the per-edge path runs, so this leg and the store\n// legs answer the same refusal to the same request. It is never skippable.\nfunc (r *uowApplyRun) runEndGate(ctx context.Context) error {\n\tif len(r.edges) == 0 {\n\t\treturn nil\n\t}\n\tvar pairs [][2]string\n\tfor _, applied := range r.edges {\n\t\tif !types.IsSchedulingEdge(applied.dep.Type) {\n\t\t\tcontinue\n\t\t}\n\t\tpairs = append(pairs, [2]string{applied.dep.IssueID, applied.dep.DependsOnID})\n\t}\n\tcyclePath, err := r.uw.DependencyUseCase().CycleThroughEdges(ctx, pairs)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"final cycle check failed (no edges added): %w\", err)\n\t}\n\tif cyclePath != \"\" {\n\t\treturn domain.NewCycleError(\"dependency cycle would be created: %s (no edges added; run 'bd dep cycles' for analysis)\", cyclePath)\n\t}\n\tfor _, applied := range r.edges {\n\t\tif storageissueops.IsExternalDepTarget(applied.dep.IssueID, applied.dep.DependsOnID) {\n\t\t\tcontinue\n\t\t}\n\t\tif err := r.uw.DependencyUseCase().ValidateBlockingHierarchy(ctx, applied.dep); err != nil {\n\t\t\treturn &publicops.ItemError{\n\t\t\t\tIndex:   applied.index,\n\t\t\t\tKind:    publicops.ItemDepAdd,\n\t\t\t\tIssueID: applied.dep.IssueID,\n\t\t\t\tErr:     err,\n\t\t\t}\n\t\t}\n\t}\n\treturn nil","sourceCodeStart":492,"sourceCodeEnd":528,"githubUrl":"https://github.com/gastownhall/beads/blob/71377f276968b452ee607177637970a4ff888584/internal/storage/uow/batch_applier.go#L492-L528","documentation":"The batch applier's end gate re-checks for dependency cycles through all edges applied in the batch; this error wraps a failure of that check call itself (CycleThroughEdges returned an error), not the detection of an actual cycle. Because nothing was committed ('no edges added'), the whole batch can be safely retried once the cause is fixed.","triggerScenarios":"runEndGate calls DependencyUseCase().CycleThroughEdges(ctx, pairs) after all items applied and the underlying query fails — DB connectivity loss, transaction/lock errors, timeout on large pair sets.","commonSituations":"Database connection dropped mid-batch (timeout, restart); Dolt transaction aborted; oversized batches making the cycle query time out.","solutions":["Retry the batch after connectivity is restored — nothing was committed","Reduce batch size if the cycle check query is timing out","Check DB health/logs for the wrapped root error (connection refused, lock wait, etc.)","Split the batch into smaller groups so the end-gate query has fewer pairs to analyze"],"exampleFix":"// before\nbatch of 5000 items -> end-gate cycle query times out\n// after\nsplit into chunks of e.g. 200 items and apply sequentially","handlingStrategy":"retry","validationCode":"// pre-check cycles client-side before submitting dep-add batches\nif path := detectCycleLocally(existingEdges, newPairs); path != \"\" {\n    return fmt.Errorf(\"batch would create cycle: %s\", path)\n}","typeGuard":null,"tryCatchPattern":"err := applyBatch(ctx, batch)\nif err != nil && strings.Contains(err.Error(), \"final cycle check failed\") {\n    // safe to retry: nothing was committed ('no edges added')\n    return retryWithBackoff(func() error { return applyBatch(ctx, batch) })\n}","preventionTips":["Check dependency cycles before large batches ('bd dep cycles')","Keep batches modest in size so the end-gate query stays fast","Ensure stable DB connectivity during batch applies","Remember this error leaves the batch unapplied — retries are safe"],"tags":["database","cycle-detection","batch","transaction"],"backgroundTag":"cycle-check-failed","analyzedSha":"71377f276968b452ee607177637970a4ff888584","analyzedAt":"2026-08-30T18:55:39.744Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}