Rescuing an 18MB Claude Code Session: When the Context Hits the Ceiling and /compact Returns 400

Abstract
A long-running Claude Code session suddenly stopped on every request. The error read: API Error 400, this model's maximum context length is 1048576 tokens, but 1058665 were requested, with 930665 in the messages and 128000 in the completion. The session file was 18MB. Even /compact returned the same 400. This article reconstructs that incident in full. It breaks down the token arithmetic, explains why /compact cannot rescue an overflowed context, identifies three compounding root causes, gives a three-step recovery order, and details the configuration changes that prevent the failure. It also covers how to rebuild context quickly after a reset, using memory files, session JSONL tails, and workspace documents. The material is based on a technical note published by Sukha on 2026-11-03.
1. The Recovery Order First
Before the analysis, the priority sequence should be stated plainly.
- Exit the process, then restart with claude --resume and a reduced output reservation.
- Immediately run /compact after the restart.
- If it still returns 400, run /clear, then continue from a reconstruction document. The session JSONL is not lost.
Do not reach for /clear first. The rest of this article explains why the order matters.
2. The Incident
A Claude Code session was running a long task. Suddenly all requests failed. The raw error was:
API Error: 400 This model's maximum context length is 1048576 tokens.
However, you requested 1058665 tokens (930665 in the messages, 128000 in the completion).
The numbers break down as follows:
- 1048576 is the model ceiling. The model is deepseek-v4-pro with a 1M context.
- 930665 is the message content itself.
- 128000 is the space reserved for output.
- 930665 plus 128000 equals 1058665, which exceeds 1048576 by roughly ten thousand tokens.
The critical fact is that after the ceiling is exceeded, even /compact returns the same 400. The rescue path is not obvious, and it requires understanding why compression fails.
3. Why /compact Cannot Rescue an Overflowed Context
Many users assume /compact works as a local truncation. It does not. The mechanism works by sending the entire conversation record to the model so the model can write a summary. When the context is already over the limit, that full record cannot be sent either. The sequence is a deadlock:
- The request exceeds the limit, so it returns 400.
- /compact must first send the full context, so it also returns 400.
- The system is stuck.
This is why demand must be reduced before compression. Compression cannot be expected to trigger on its own. Lower the requirement first, then compact.
4. Three Compounding Root Causes
The root causes stack on top of each other.
| # | Cause | Explanation |
|---|---|---|
| 1 | Model hard ceiling | Messages plus output reservation exceed the context limit, so the request physically cannot be sent |
| 2 | Auto-compact did not catch it | The configuration pushed the compact window to the model ceiling of 1M, leaving no margin. Compression never triggered because the wall was hit first |
| 3 | /compact shares the same failure | It must also send the full context, so it fails together with the limit |
Cause 2 is the most damaging. Setting the compact window to 1M looks like maximizing context utilization, but it effectively removes the safety belt. A window at the ceiling gives compression no room to fire before the request is rejected.
5. Three-Step Handling
Step 1: Exit and Restart with a Smaller Output Reservation
Environment variables are read only at process startup. Changing configuration inside the original session has no effect. Restart with --resume instead:
export CLAUDE_CODE_MAX_OUTPUT_TOKENS=65536 # output reservation 128K -> 64K
claude --resume
The effect: a 930K message plus a 64K output reservation is under 1M, so the session becomes usable again. Step 1 does nothing else. Its only goal is to let the session send requests again.
Step 2: Immediately Run /compact
Once the session recovers, compact right away. This pushes the context back to a safe water level, and normal work can continue.
Step 3: If Still Failing, Use /clear. Data Is Not Lost
If the resume still returns 400, /clear empties the context. Do not fear losing data.
- The session JSONL is fully preserved under ~/.claude/projects//.
- The memory files under ~/.claude/projects//memory/ are not affected by /clear.
- Claude Code automatically re-reads CLAUDE.md and AGENTS.md to re-anchor.
6. Prevention: Two Configuration Changes Are Enough
Edit ~/.claude/settings.json, and back it up first:
{
"env": {
"CLAUDE_CODE_AUTO_COMPACT_WINDOW": "800000",
"CLAUDE_CODE_MAX_OUTPUT_TOKENS": "65536"
}
}
- Compact window from 1M to 800K. When messages reach 800,000, auto-compact fires, leaving ample room for output.
- Output reservation from 128K to 64K. This directly gives 64K back to the messages.
The env block only applies to newly started processes. After the change, exit and reopen. The result can be verified. /context shows a line like:
Model: deepseek-v4-pro Tokens: 358.2k / 800k (45%)
The denominator changing from 1M to 800k confirms the configuration took effect.
7. Rebuilding Context Quickly After a Blowout
This part is more valuable than the rescue itself: letting a new session re-anchor on documents instead of relying on an overlong context.
Step A: Extract Facts from Three Places
- memory/*.md. Claude Code records its own rules and conclusions there.
- The tail of the session JSONL. This holds the most recent user messages and tool calls.
- Workspace documents. These are the explanations already present in the project.
Step B: Write a Reconstruction Document with Five Fixed Sections
- Identity and recovery path.
- Rules that must be followed.
- Work that was just completed.
- Ongoing work and questions still to answer.
- Document and memory pointers.
Step C: Extract Key Information from the JSONL with a Script
A Python script reads the session JSONL and separates user messages, assistant replies, and tool calls.
import json
path = "/home/zms/.claude/projects/<project-slug>/<session-id>.jsonl"
users, tools, asst = [], [], []
with open(path, encoding="utf-8", errors="replace") as f:
for line in f:
try:
d = json.loads(line)
except:
continue
t, msg = d.get("type"), d.get("message") or {}
c = msg.get("content")
if t == "user":
if isinstance(c, str):
users.append(c)
elif isinstance(c, list):
for p in c:
if p.get("type") == "text":
users.append(p.get("text"))
elif t == "assistant":
for p in c:
if not isinstance(p, dict):
continue
if p.get("type") == "text":
asst.append(p.get("text"))
elif p.get("type") == "tool_use":
tools.append((p.get("name"), json.dumps(p.get("input", {}), ensure_ascii=False)[:200]))
for u in users[-20:]:
print(f"[USER] {u.replace('\n', ' ')[:200]}")
for a in asst[-10:]:
print(f"[ASST] {a.replace('\n', ' ')[:150]}")
for t in tools[-5:]:
print(f"[TOOL] {t[0]}: {t[1][:300]}")
The incident session file was 18MB. It contained 156 user messages, 2616 assistant replies, and 1113 tool calls, with 703 of those being Bash alone. This script makes it possible to see quickly what the session was doing.
8. Observability as the Missing Layer
The incident has a broader engineering lesson. Context pressure builds silently. The failure appears only when a request is rejected, and by then the session is already in a deadlock state. Teams that rely on one model and one client get visibility only at the failure point.
When an agent workflow spans multiple models and providers, usage accounting becomes harder. Each provider reports tokens through its own console, and none of them agree on a single view of the conversation. A centralized control plane changes this. An API gateway records every call, the model that served it, and the token counts, in one place. With a platform such as 4sapi, a team can watch context utilization across the whole loop, set alerts before the ceiling is reached, and route a failing call to a model with more headroom. The lesson from the 1M ceiling generalizes: track usage proactively, reserve margin, and act before the wall, not after the 400.
9. Daily Habits That Prevent the Failure
Three small habits reduce the chance of ever hitting this state.
- Check /context often. When the count reaches 800,000, run /compact proactively instead of waiting for an error.
- Set the auto-compact window in the env block to 800k. This is the safe water level.
- Clean up periodically. Archive old sessions under ~/.claude/projects//sessions/*.jsonl, and only clean them after confirming that the memory has been consolidated.
10. Version and Timeliness
| Item | Value |
|---|---|
| Claude Code version | 2.1.308 |
| Incident date | 2026-11-02 |
| Model | deepseek-v4-pro (1M context) |
| Reminder | Context management and compact strategy vary across versions. After an upgrade, check the window value on the first /context |
Conclusion
The incident shows how a single configuration choice can turn a safe system into a fragile one. Setting the compact window to the model ceiling removed the margin that compression needs. The deadlock was not a bug in /compact. It was a consequence of the context limit and the request that exceeded it.
The recovery order works because it reduces demand before attempting compression. Exiting and restarting with a smaller output reservation brings the request back under the limit. /compact then has room to operate. /clear remains the last resort, and it is safe because the JSONL, the memory files, and the anchor documents survive.
The deeper takeaway is that context is a finite, billable resource. It must be measured, reserved, and managed like any other production constraint. Monitoring it before the ceiling, setting compression windows with margin, and rebuilding from documents after a reset turn a panic into a routine operation.
International access: https://4sapi.com
Domestic access: https://4sapi.org
Comments
Join the discussionNo comments yet. Be the first to comment.



