Once a session transcript trips AUP, --continue/--resume is permanently blocked with no in-product recovery
Once a session transcript trips AUP, --continue / --resume is permanently blocked with no in-product recovery
Summary
If a Claude Code session receives a Usage Policy refusal at any point, the transcript on disk becomes permanently unrecoverable via claude --continue or claude --resume. Every subsequent prompt — including a trivial Hello? — re-sends the same accumulated transcript to the API, the classifier re-fires, and the session stays bricked.
The only fix is to hand-archive the offending .jsonl out of ~/.claude/projects/<encoded-cwd>/. There is no in-product recovery path (no /branch, no /trim, no warning on --resume).
For long-running engineering sessions this is a continuity nightmare: hours of session-local context can be lost to a single transient classifier flag.
Environment
- Claude Code 2.1.133 (CLI)
- macOS (Darwin 25.4.0)
- Model: Claude Opus 4.7 (
claude-opus-4-7, 1M context variant) - Long-running engineering session inside a single project dir
Repro
- Run a long Claude Code session in one project directory; let the transcript on disk grow large (in my case,
~/.claude/projects/-Users-<user>-<path>/<uuid>.jsonlreached 99 MB / 33,099 lines). - At some turn (line 32,984 in my transcript) the API returns:
````
API Error: Claude Code is unable to respond to this request, which appears
to violate our Usage Policy (https://www.anthropic.com/legal/aup). ...
Request ID: req_011Cb91nV4jbiF8iatdTAGDn
- Press
escand try any new prompt —Hello?is sufficient. - Every subsequent turn fires the same AUP refusal with a fresh request ID.
- Exit. Re-enter the project with
claude --continue(orclaude --resume <session>). - The new session loads the same poisoned transcript and AUP-refuses on the first turn again.
- Repeat with
claude(no flag) in a fresh session — works fine; project files (CLAUDE.md,project-state.md) are not the trigger by themselves.
Expected behavior
A single transient AUP refusal should not brick continuation of an otherwise-clean session. Reasonable possibilities:
- Warn on
--continue/--resumewhen the target transcript contains prior AUP refusals. - Offer to branch from the last good turn (everything before the first AUP-refused exchange).
- Provide
/trim Nor/branchto drop the trailing N turns. - Provide a sanitizing
/savethat exports a clean snapshot suitable for resumption.
Actual behavior
- No warning on
--continue/--resume. - No in-product trim or branch.
- The only workaround is to
mv ~/.claude/projects/<encoded-cwd>/<uuid>.jsonlout of the project directory, losing all conversation context for that session.
Workaround (what I did)
mkdir -p ~/.claude/projects/_archived-aup-blocked
mv ~/.claude/projects/<encoded-cwd>/<offending-uuid>.jsonl \
~/.claude/projects/_archived-aup-blocked/
# also move any later .jsonl in the same project dir that has AUP entries —
# they likely resumed from the poisoned one and are now poisoned themselves.
claude # fresh session, NO --resume / --continue
I rebuild session context from project-level files (CLAUDE.md, a hand-maintained project-state.md) and git log / git diff. The transcript content is lost.
Why this matters
- Continuity loss. Long engineering sessions accumulate decisions, plans, and partial-state reasoning that are not in code yet. Losing the transcript loses that.
- No diagnostic. The refusal message gives a request ID but no indication of which turn or content tripped it, so users can't selectively trim. (Related to #51248 and #6830.)
- Cumulative-weight false positives are plausible. In my case a metadata scan of the 20 entries before the first AUP refusal found no obvious refusal-worthy keyword matches — routine tool calls, code, Bash output. (I did not read raw content into a working session in case it would poison that one too.) The trip appears to be cumulative context weight at very long conversations rather than a single offending message, though I can't rule out a specific message I didn't inspect. Either way, long-running engineering sessions are at risk.
- Silent contagion across sessions. A follow-up session that uses
--resumeinherits the poison and itself becomes AUP-blocked on turn 1. The user has no way to tell from the CLI which transcripts are "tainted."
Suggested fixes (in rough priority order)
- Warn on resume when the target
.jsonlcontains any prior AUP refusal in the assistant message stream. One-line warning +--forceto override would be enough. /branchor/trimto drop the most recent N turns and continue, or to branch from a chosen turn index.- AUP-aware
--continue: silently drop the trailing AUP-refused exchanges (they have no semantic value — they're refusals, not work) and resume from the last successful assistant turn. - Contextual diagnostic (overlaps with #51248): when AUP fires inside an established session, surface which turn range was implicated, so users can self-trim.
Notes for the maintainers
- This is not a request to weaken the safety filter. AUP firing once is fine. The bug is that there is no in-product way to continue past it without filesystem surgery.
- I'm filing this from a working session that I started fresh after hand-archiving the poisoned transcript. The fresh session has the same project files and same CLAUDE.md and works without issue, which is what convinced me the trigger is cumulative transcript weight rather than the project context.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗