Skip to content

Troubleshooting

Common recovery patterns for stuck tasks, broken state, Ralph debugging, and review-backend conflicts. For deeper subsystem guides see the flowctl CLI reference, Ralph internals, and the source repository.

No. Setup copies nothing into your repo, so a plugin update (/plugin update, droid plugin update, or git pull + re-install on Codex/Cursor) is the whole update: every skill resolves flowctl from the plugin install itself, and the agent guide comes from flowctl usage. Re-run /flow-next:setup only when setup tells you the docs-snippet schema bumped, or when you want to change configuration or re-seed the user-owned files. It stays idempotent and non-destructive - your specs, tasks, memory, and config are untouched.

Delete it. .flow/bin/, .flow/templates/spec.md, and .flow/usage.md are snapshots from the retired copy layout; nothing reads them, and removing them changes nothing observable in any workflow. One exception before you bulk-delete: a .flow/templates/spec.md you EDITED is your content - copy it to a repo-root SPEC.md first (that is the customization point now); setup’s cleanup offer detects a differing template and never deletes it for you. Keeping leftovers is a hazard, not a safety net - a stale copied flowctl can shadow the current one, and a flowctl flag that “should exist” erroring is the classic symptom. /flow-next:setup detects the leftovers and offers to delete them (/flow-next:plan prints a one-line nudge and moves on); you can also remove them yourself (use git rm for tracked copies).

Two specs share the same number (fn-122 twice)

Section titled “Two specs share the same number (fn-122 twice)”

Symptoms: flowctl validate --all reports a duplicate ordinal, or bare fn-122 refuses to resolve and lists two candidates.

What it means: two full ids like fn-122-foo-bar and fn-122-other-slug exist. The full id is the identity (filesystem path, branch, task ids). A shared ordinal is untidy, not broken - validate treats it as a warning, not a root error.

What to do:

  1. Do not renumber. Ids never change. They already live in commits, branches, tags, PR bodies, tracker comments, and memory entries you cannot rewrite safely.
  2. Prefer the full slug when the bare form is ambiguous. The resolver lists candidates and requires the full id (same idea as git short-hash disambiguation).
  3. Avoid it next time. With a tracker configured, set the team default so new specs mint from the issue key instead of racing on fn-N:
Terminal window
flowctl config set tracker.specIds tracker

Native allocation is also wider than it used to be - it scans every registered worktree and every ref, not only the local working tree - which closes most same-repo parallel creates. Separate clones that have not fetched each other can still collide; that is what tracker-keyed ids are for. Details: Collaboration, Tracker Sync.

Terminal window
# Check task status
flowctl show fn-1.2 --json
# Reset to todo (from done/blocked)
flowctl task reset fn-1.2
# Reset + dependents in same spec
flowctl task reset fn-1.2 --cascade

--cascade walks the spec’s depends_on graph and resets every downstream task that referenced the target, so the next flowctl ready call surfaces them again.

Run manually in terminal (not via AI agent - destructive command guards block agents from running rm -rf):

Terminal window
# Remove all flow state (keeps git history)
rm -rf .flow/
# Re-initialize
flowctl init

Or run /flow-next:uninstall to clean up docs and get the commands printed for manual execution.

Terminal window
# Check run progress
cat scripts/ralph/runs/*/progress.txt
# View iteration logs
ls scripts/ralph/runs/*/iter-*.log
# Check for blocked tasks
ls scripts/ralph/runs/*/block-*.md

Each Ralph run lives under scripts/ralph/runs/<timestamp>/. The directory contains the iteration log, receipts (review / walkthrough / blocked), and an optional progress.txt tail. Deep dive: Ralph internals.

Terminal window
# Check receipt exists
ls scripts/ralph/runs/*/receipts/
# Verify receipt format
cat scripts/ralph/runs/*/receipts/impl-fn-1.1.json
# Must have: {"type":"impl_review","id":"fn-1.1",...}

Ralph reads receipts to decide whether to advance, retry, or block. A missing or malformed receipt freezes the loop. The bundled flowctl validate --all checks state-file shape; receipt-shape errors usually mean a backend wrote the file mid-iteration and the loop crashed.

Review loop stalls, repeats unchanged work, or runs away

Section titled “Review loop stalls, repeats unchanged work, or runs away”

Symptoms: a plan/impl/completion review loops far more than the round cap - the field report was ~11x on a large ticket before the reviewer and implementer converged. Most common on the Cursor review backend, but the underlying causes were backend-agnostic.

What was happening (root causes, now bounded):

  • The cap was prose-only and reset every invocation. MAX_REVIEW_ITERATIONS (then default 4; now 8) was an instruction to the host LLM to keep an in-context counter - but it reset to 0 on every fresh review invocation (a new Ralph iteration, a new pilot tick, a human retry). The runaway was about 5-6 fresh invocations x ~3 in-agent rounds. Now flowctl owns a cumulative counter on spec state that survives fresh invocations and refuses at the cap (exit 4 + ESCALATE:).
  • Every re-review was a fresh blind review (a churn lottery - two identical fresh Cursor reviews overlapped on only ~50% of findings, so SHIP was statistically near-unreachable within the cap). The convergence ratchet now renders the validated structured findings (severity, classification, status) with labeled legacy prose only as fallback. Its shrink-only contract remains: verify each prior finding fixed; only a NEW >= Major finding may block; all prior fixed + no new >= Major means MUST SHIP.
  • Codex/copilot verdicts could be poisoned by a verdict literal echoed in tool output (e.g. a grep of smoke_test.sh’s assertions), making flowctl report SHIP while the reviewer said NEEDS_WORK - a false SHIP or a false NEEDS_WORK that kept a loop alive. The parse now isolates the final agent message (last-match).
  • Cursor’s ambient injection (its built-in persona rubric + auto-attached AGENTS.md) diluted the scope anchor. A persona-override preamble now rides in every cursor review prompt (see Orchestration).

What the loop can do on its own now: the cap reads the structured findings each verdict persists and ends a measurably stuck loop early - exit 4 with ESCALATE: review loop stalled (<rule>) - and a reviewer can return NEEDS_HUMAN when the next step is a judgment call, which persists its receipt and status before exiting 4 with ESCALATE: reviewer requested human review. Re-dispatching an unchanged artifact is refused before it costs a round (NOT_RETRYABLE: artifact unchanged since last verdict, exit 1).

What to do when it escalates:

  • NOT_RETRYABLE (exit 1) consumed nothing. Change the actual reviewed artifact, or decide as a human whether an explicit re-plan is warranted - do not blindly retry.
  • Either ESCALATE: variant (exit 4) is NOT retryable. Under Ralph/autonomous it surfaces as NEEDS_HUMAN. Inspect the persisted receipt and findings trail, then decide: redesign, focused fix, or re-plan (the reviewer strictness is often signal - big/ambiguous plans really do re-fail).
  • After an explicit re-plan (you rewrote the spec/approach, not just patched a finding), a human can reset the counter to re-open the cap: flowctl spec reset-review-rounds <spec-id> (add --impl to also clear per-task impl-review counters). A SHIP verdict resets automatically. Ralph blocks reset commands and --force - they are human-only recovery tools, never autonomous ones.
  • The default cap is 8. Tune MAX_REVIEW_ITERATIONS (env / Ralph config.env) for a genuinely large ticket, but the cap stays enabled and escalation stays preferable to a larger budget.
  • Full semantics: flowctl CLI reference and Ralph review loops.

Symptom: a review prints one stderr line like

warning: codex model '<ranking-top id>' unavailable; downgraded to '<available id>'. Cached for this CLI version.

(or ... fell back to the never-fail floor (the CLI default / 'auto')), and the review’s receipt records the downgraded id / auto / default rather than the ranking top.

This is expected, not an error. Flow-Next dispatches the strongest model by default and, when the local CLI can’t run it, transparently resolves the best available one (the model-resolution ladder). It fires ONLY on the distinctive model-unavailable signature (codex “requires a newer version of Codex”, copilot ... from --model flag is not available, cursor Cannot use this model: ..., claude an exit-0 error payload whose text names the selected model, or the [claude-code:unrecognized_model] stderr tag); auth / network / sandbox / timeout failures propagate unchanged.

What to do:

  • Want the top model? Upgrade the backend CLI. The cache key is (backend, CLI version), so the upgrade re-resolves automatically on the next review.
  • The downgrade repeats every review? It shouldn’t - the result is memoized in .flow/.cache/model-resolution.json. If it does, that file may be unwritable (check permissions) or you’re on a fresh CLI version each run.
  • Force a specific model (skip the ladder + cache entirely): pin it explicitly - --spec codex:<model-id>, a per-task/per-spec review: value, FLOW_CODEX_MODEL, or review.backend. An explicit unavailable model errors clearly instead of downgrading.
  • Reset the cache: rm -rf .flow/.cache/ - it is regenerated (and gitignored) on the next review; a corrupt file is already treated as a cold start.

Custom RepoPrompt CLI instructions conflicting

Section titled “Custom RepoPrompt CLI instructions conflicting”

Flow-Next’s plan-review and impl-review skills include specific instructions for CE-first CLI discovery, window selection, builder workflow, and chat commands. Custom instructions can override these and cause unexpected behavior.

Symptoms:

  • Reviews not using the correct RepoPrompt window
  • Builder not selecting expected files
  • Chat commands failing or behaving differently

Fix: Remove or comment out custom RepoPrompt CLI instructions from your CLAUDE.md/AGENTS.md when using Flow-Next reviews. The plugin provides the complete CE-first workflow.

Windows: python3 not found / Microsoft Store alias stub

Section titled “Windows: python3 not found / Microsoft Store alias stub”

Symptom: on Windows, flowctl fails with “Python was not found; run without arguments to install from the Microsoft Store…” and exit code 9009, even though you installed real Python.

Cause: python3 resolves to the Microsoft Store App Execution Alias - a 0-byte reparse point at %LOCALAPPDATA%\Microsoft\WindowsApps\python3.exe that Windows ships enabled by default. When your real Python came from python.org or the py launcher (not the Store), the stub shadows it: it satisfies command -v python3 (it is on PATH) but is non-functional. Older flowctl launchers trusted presence over function and picked the stub - so flow-next broke on every Windows machine in this configuration.

The shipped fix (no action needed on a fresh install): the flowctl launchers now probe interpreter functionality - each candidate must actually run <cand> -c "import sys" and exit 0 - in order $PYTHON_BIN then py -3 then python3 then python, so the 9009 stub is skipped. A flowctl.cmd batch shim ships alongside the extensionless bash flowctl, so PowerShell / cmd.exe (Claude Desktop, native Codex, native Cursor) resolve a working interpreter too.

Recovering a legacy copied install (a pre-fix .flow/bin/flowctl hardcodes exec python3 and cannot fix itself). This only applies to repos still carrying the retired copy layout. Pick either:

  1. Delete the copy (recommended, durable). The plugin’s own launchers already carry the fix, and nothing reads .flow/bin/ any more:

    Terminal window
    Remove-Item -Recurse -Force .flow\bin # git rm -rq .flow/bin if it is tracked

    After this, flowctl (Git Bash / WSL) and the flowctl.cmd sibling (cmd.exe / PowerShell) resolve from the plugin install. The copy-less chain is untested live on Windows - best-effort; report breakage. /flow-next:setup offers the same deletion interactively.

  2. Disable the Store alias (per-machine OS workaround). Settings, then Apps, then Advanced app settings, then App execution aliases: toggle OFF for python.exe and python3.exe. python3 then resolves to your real install. Note the py launcher is not included with Store Python, so if you were relying on Store Python, install python.org Python (which ships py) to get py -3.

Prefer path 1 - the alias toggle is per-machine, not durable, and does not survive a fresh Windows profile.

Sources: Microsoft Learn Python on Windows FAQ (the App Execution Alias stub + “the py launcher is not included with Store Python” + disabling the alias); python.org Using Python on Windows and PEP 397 (the py launcher / py -3).

/flow-next:map: clawpatch not found / version mismatch / Node 20

Section titled “/flow-next:map: clawpatch not found / version mismatch / Node 20”

/flow-next:map wraps the upstream clawpatch CLI. Common failure modes:

1. clawpatch binary missing. Skill prints pnpm add -g clawpatch install instructions verbatim and exits 1. No auto-install - global npm/pnpm installs are user-consent territory.

Terminal window
# Recommended: install globally with pnpm
pnpm add -g clawpatch

2. pnpm installed clawpatch but it’s not on PATH. pnpm installs global binaries under $PNPM_HOME and needs a one-time pnpm setup to wire PATH - without it, the install lands but the binary isn’t resolvable. (Exact location varies by pnpm version and OS: ~/.local/share/pnpm on many setups, $PNPM_HOME/bin/ on others - pnpm bin -g reports yours.) Skill detects pnpm bin -g exit-0 + command -v clawpatch exit non-zero and prints the PNPM_HOME hint:

Terminal window
pnpm setup # writes PNPM_HOME + adds it to your shell rc
source ~/.zshrc # or ~/.bashrc - pick up the new PATH entry
command -v clawpatch # should now resolve

3. clawpatch --version falls outside the tested range. The skill carries a single-source SUPPORTED_CLAWPATCH version range in its prose. Outside range emits a one-line stderr warning naming expected vs found and continues (degrades - never blocks). Re-pin lands on each clawpatch minor.

4. Node 20 with clawpatch installed. clawpatch’s engines.node: ">=22" triggers its own error; the skill propagates it verbatim. Upgrade Node 22+ (e.g. nvm install 22 && nvm use 22) or skip /flow-next:map - scouts gracefully fall back to the grep/glob path when .clawpatch/ is absent.

5. “Should I commit .clawpatch/ to the repo?” No - by default the skill writes a .clawpatch/.gitignore with * + !.gitignore, making the feature index local-per-developer. The map is regenerable from clawpatch map, the schema may flip between pre-1.0 minor releases, and committing it creates PR review noise + merge conflicts. The full trade-off table is on the Map skill page. Teams that want shared indexes can customize the skeleton - unsupported, but the skill won’t clobber a customized .gitignore on re-run.

The skill is opt-in convenience - flowctl core never imports or requires clawpatch; nothing else in flow-next breaks when the skill can’t run.

Run manually in terminal (DCG blocks these from AI agents):

Terminal window
rm -rf .flow/ # Core flow state
rm -rf scripts/ralph/ # Ralph (if enabled)

Or use /flow-next:uninstall which cleans up docs and prints commands to run. Doc cleanup removes two independent marker blocks from CLAUDE.md/AGENTS.md: the <!-- BEGIN FLOW-NEXT --><!-- END FLOW-NEXT --> instructions block and, if /flow-next:setup scaffolded one, the <!-- flow-next:model-routing:start --><!-- flow-next:model-routing:end --> model-routing block (removed only when its marker pair is well-formed - a damaged pair is reported and left untouched). GLOSSARY.md and STRATEGY.md at the repo root are intentionally preserved - they outlive flow-next per the survives-uninstall invariant.

Cursor in-IDE browser MCP missing (cursor-ide-browser)

Section titled “Cursor in-IDE browser MCP missing (cursor-ide-browser)”

On Cursor, drive / QA probes the built-in browser by MCP id cursor-ide-browser. A catalog miss is not absence.

  1. Settings → Tools & MCP → Browser Automation = Browser Tab.
  2. Type @Browser in chat (no space), or open the Browser pane until it shows connected.
  3. Let the agent re-probe once. Do not loop.

A mid-run MCP server does not exist: cursor-ide-browser after the pane was already driving is a known Cursor flake. @Browser does not restore that session - quit Cursor fully, wait ~10s, confirm the pane is connected, start a fresh chat. See Flow-Next Drive and Install → Cursor.

A cached install can keep surfacing a skill under its old name after a rename (browser became flow-next-drive in 1.4.0). It auto-clears within about seven days as the plugin cache refreshes. To clear it immediately, delete the stale cached marketplace directory under your host’s plugin cache path and reload the host.

Terminal window
rm -rf ~/.claude/plugins/cache/<marketplace> # then reload Claude Code