Troubleshooting
Is it the app, or the setup? Compatibility lists
the Node.js, Playwright, browsers, agent SDK versions and recording
format this release supports and was tested with. Check
npx saffron --version against it first: a failure on a combination it
does not list may not be your app's.
saffron accept says the proposal is stale. The scenario or the
committed recording changed after the proposal was filed, so the diff you
would be approving is not the one that was made (§5). Run the scenario
again for a fresh proposal, or reject this one.
A recording ends with "Autocompact is thrashing" or another
context-window error from Claude Code. One browser tool result was too
big for the session, typically a whole API response body fetched with
browser_network_request. Saffron cuts every browser tool result at
60,000 characters and tells the agent to ask for less, so this no longer
ends a session; if you still see it, the page itself is enormous. Split
the scenario, or point the step at a smaller region of the page.
A run says "The recording cannot be read" and names a field. The cache
file is not in the shape this runner writes: a hand edit, a bad merge, or
a recording from a newer saffron-ai. Fix the field it names, update the
runner if the message says so, or re-record with --rerecord.
A cached scenario keeps failing and the recording looks wrong (an empty value where the step passes one, a click on the wrong control). Do not edit the JSON. Re-record it:
npx saffron run --rerecord --filter @tag # or a feature path
--rerecord discards the selected scenarios' caches and lets the agent
record them fresh (it refuses, deleting nothing, in a run that could not
record them again: only Firefox or WebKit, or an agent that cannot start), seeded from every other recording, then files a
proposal for review as usual. The rows of a Scenario Outline share one
recording, so re-recording one row (login.saffron:17, or --filter on
one Examples block's tags) runs every row: that row records first and the
others replay the new recording. A first recording does the same: a run
that picks some rows of an outline not recorded yet runs them all. Two guards make this rarer: the recorder
flags a fill recorded with an empty value on a step that passes one (the
proposal arrives UNVERIFIED with the reason; a step that clears the
field, or an Examples row whose value is blank, is not flagged), and saffron accept --all
skips UNVERIFIED proposals unless you pass --include-unverified or
accept that file explicitly.
| Symptom | Cause & fix |
|---|---|
Cache is stale (feature file changed) |
Step text no longer matches the recording. With the agent on, it re-records automatically; review the new proposal. |
Red with --no-agent on a new scenario |
No cache exists. Run once with the agent to record. |
| Scenario heals on every run | Something volatile is baked into the cache (a literal price/date). Reject, re-record, the agent's rules now capture/pattern these, or hand-edit the cache JSON (it's yours). |
Agent invocation failed: … maximum number of turns |
Very long scenario. Raise maxTurns in config. |
| Login wall in every scenario | Configure storageState (§8). |
| First run seems slow | That's recording (minutes per scenario). Replays are seconds. Record once, replay forever. |