[Bug]: Claude 200k context window selection is a no-op; sessions always run at 1M
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 23k
- Forks
- 5.9k
- Avg merge
- 11h 14m
- Merged PRs (30d)
- 357
Description
Before submitting
- I searched existing issues and did not find a duplicate.
- I included enough detail to reproduce or investigate the problem.
Area
apps/server
Steps to reproduce
- Pick Claude Opus 5 (or Fable 5 / Sonnet 5) in the composer.
- Set Context Window → 200k.
- Send a turn.
- Inspect what the provider actually ran — e.g. read
modelUsage[<model>].contextWindowoff the SDK result, or look at themaxTokensvalues T3 persists inorchestration_events.
The session runs at 1,000,000 tokens, not 200,000. The 200k selection has no effect on the request.
Expected behavior
Selecting 200k should make Claude Code run the 200k context window.
Actual behavior
The 200k selection is a no-op. resolveClaudeApiModelId (apps/server/src/provider/Layers/ClaudeProvider.ts:458) encodes the choice purely in the model slug:
export function resolveClaudeApiModelId(modelSelection: ModelSelection): string {
switch (resolveClaudeContextWindow(modelSelection)) {
case "1m": return `${modelSelection.model}[1m]`;
default: return modelSelection.model; // assumed to mean 200k
}
}
The bare slug does not mean 200k. Claude Code auto-enables the 1M window for these models unless the process env sets CLAUDE_CODE_DISABLE_1M_CONTEXT=1. So T3 spawns --model claude-opus-5, and the session runs at 1M anyway.
Three runs, same SDK (@anthropic-ai/claude-agent-sdk 0.3.170) and same binary (Claude Code 2.1.247), reading modelUsage[].contextWindow off the result message:
| model passed | env | actual context window |
|---|---|---|
claude-opus-5 |
default | 1,000,000 |
claude-opus-5[1m] |
default | 1,000,000 |
claude-opus-5 |
CLAUDE_CODE_DISABLE_1M_CONTEXT=1 |
200,000 |
Same via the bare CLI, no SDK involved:
$ claude --model claude-opus-5 --output-format json -p "hi" | jq '.modelUsage | map_values(.contextWindow)'
{ "claude-opus-5": 1000000 }
Confirmed for all three models that expose the Context Window trait: claude-opus-5, claude-fable-5, claude-sonnet-5 all report 1,000,000 when passed as a bare slug.
Not environment-specific — reproduces identically on a local server and on a desktop-managed SSH remote. In both cases the selection reaches the server intact (projection_threads.model_selection_json contains {"id":"contextWindow","value":"200k"}) and the spawned process has a clean env and --model claude-opus-5.
Impact
Major degradation or frequent failure
Version or commit
0.0.36-nightly.20260827.1205
Environment
macOS 26.6.2 + Linux SSH remote; Claude Code 2.1.247; @anthropic-ai/claude-agent-sdk 0.3.170; Claude Max OAuth
Logs or stack traces
# T3 persists Claude Code's own report of the live window.
# A thread whose stored selection is 200k:
# projection_threads.model_selection_json
# {"instanceId":"claudeAgent","model":"claude-opus-5",
# "options":[{"id":"effort","value":"xhigh"},{"id":"contextWindow","value":"200k"}]}
# orchestration_events payloads for that thread:
# {"maxTokens": 1000000} x60
Workaround
None from the UI. Selecting 1M vs 200k makes no difference to the request; both run at 1M.
Suggested fix
Set the env var alongside the slug, at the single queryOptions site in apps/server/src/provider/Layers/ClaudeAdapter.ts:4331:
env: {
...claudeEnvironment,
...(resolveClaudeContextWindow(modelSelection) === "200k"
? { CLAUDE_CODE_DISABLE_1M_CONTEXT: "1" }
: {}),
},
One caveat for whoever picks this up: env is only read at spawn, so the query.setModel() path in sendTurn (ClaudeAdapter.ts:4531) can't flip the window on a live thread — switching 200k↔1M mid-thread would need a session restart to take effect.
Related
- #5286 — same root cause, but filed as a cosmetic meter bug. It's the reverse: the meter is the accurate part.
selectedClaudeContextWindowseeds it at 200k, then Claude Code's honest report of 1,000,000 overwrites it atClaudeAdapter.ts:2153. - #2733 — same report, closed as a duplicate of #2394. Its one comment already named
CLAUDE_CODE_DISABLE_1M_CONTEXT, but the linked PR's fork was deleted. - #2394 — closed in a maintenance sweep with "a new report would need provider request diagnostics". This report provides them.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with resolveClaudeApiModelId in apps/server/src/provider/Layers/ClaudeProvider.ts and the queryOptions env construction at apps/server/src/provider/Layers/ClaudeAdapter.ts:4331. Verify how the 200k selection reaches the spawned process, then confirm the resulting SDK contextWindow or persisted maxTokens reports 200k while 1M remains unchanged. Note that changing the selection through sendTurn cannot affect an already-running session because env is read at spawn.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- api, backend
- Issue type
- Bug
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100