[BUG] 'CLAUDE_CODE_MAX_OUTPUT_TOKENS' incorrectly validates Sonnet models against 32k limit instead of 64k

Status Fixed / completed
Maintainer reply None cached
Activity 10 comments · opened Jul 26, 2025 · closed Sep 15, 2025

Environment

  • Platform (select one):
  • [x] Anthropic API
  • [ ] AWS Bedrock
  • [ ] Google Vertex AI
  • [ ] Other: <!-- specify -->
  • Claude CLI version: 1.0.61
  • Operating System: Windows 11 with WSL2
  • Terminal: Windows Powershell (WSL2)

Bug Description

The oU0 function in Claude Code's cli.js incorrectly enforces a 32,000 token limit for all models, when Sonnet models actually support up to 64,000 tokens. The validation function uses a hardcoded 32,000 limit regardless of model type.

Steps to Reproduce

  1. Create or update ~/.claude/settings.json with:
{
  "env": {
    "ANTHROPIC_CUSTOM_HEADERS": "anthropic-beta: interleaved-thinking-2025-05-14",
    "MAX_THINKING_TOKENS": "100000",
    "CLAUDE_CODE_MAX_OUTPUT_TOKENS": "64000"
  },
  "model": "sonnet"
}
  1. Launch Claude Code in interactive mode by executing claude
  2. The following error is printed in terminal: ERROR Invalid env var CLAUDE_CODE_MAX_OUTPUT_TOKENS: 64000

Expected Behavior

The validation should respect model-specific token limits:

  • Haiku models: Allow up to 8,192 tokens
  • Sonnet models: Allow up to 64,000 tokens
  • Opus models: Allow up to 32,000 tokens

Actual Behavior

Any value above 32,000 triggers an error regardless of model type:

ERROR Invalid env var CLAUDE_CODE_MAX_OUTPUT_TOKENS: 50000

Additional Context

I've identified the exact fix needed in the minified cli.js file. The oU0 function needs to check model-specific limits.

Current implementation:

function oU0(A){if(A.includes("3-5"))return 8192;if(A.includes("haiku"))return 8192;let B=process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS;if(B){let Q=parseInt(B,10);if(!isNaN(Q)&&Q>0&&Q<=32000)return Q;else throw new Error(`Invalid env var CLAUDE_CODE_MAX_OUTPUT_TOKENS: ${B}`)}return 32000}

Fixed implementation:

function oU0(A){let maxTokens=A.includes("haiku")?8192:(A.includes("3-5")||A.includes("sonnet"))?64000:32000;let B=process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS;if(B){let Q=parseInt(B,10);if(!isNaN(Q)&&Q>0&&Q<=maxTokens)return Q;else throw new Error(`Invalid env var CLAUDE_CODE_MAX_OUTPUT_TOKENS: ${B}. Must be between 1 and ${maxTokens} for model ${A}`)}return A.includes("haiku")?8192:32000}

I've tested this fix locally and confirmed:

  • Haiku models correctly limited to 8,192 tokens
  • Sonnet models now accept up to 64,000 tokens
  • Opus models correctly limited to 32,000 tokens
  • Error messages include model-specific limits

This fix maintains backward compatibility while enabling Sonnet users to access the full 64k token capacity of their models.

---

EDIT: Additional Issue - Model Persistence in settings.json

Problem Description

When using /model in Claude CLI to switch models at runtime, the settings.json file's model field was being permanently modified:

  • Switching from default to another model would add/update the model field
  • Switching back to default (sonnet) would completely remove the model field from settings.json
  • This made it impossible to temporarily switch models without affecting the persistent configuration

Root Cause

The issue was in the em function (line 356531 in the prettified cli.js), which is an onChangeAppState handler that monitors state changes. When mainLoopModel changed, it was calling:

m3("userSettings", { model: void 0 })  // When switching to default
m3("userSettings", { model: A.mainLoopModel })  // When switching to other models

The m3 function persists settings to the user settings file, causing unwanted persistence of runtime model changes.

Solution

Modified the em function to only update runtime state without persisting to settings:

Before:

function em({ newState: A, oldState: B }) {
  if (B !== null && A.mainLoopModel !== B.mainLoopModel && A.mainLoopModel === null)
    (m3("userSettings", { model: void 0 }), HA1(null));
  if (B !== null && A.mainLoopModel !== B.mainLoopModel && A.mainLoopModel !== null)
    (m3("userSettings", { model: A.mainLoopModel }), HA1(A.mainLoopModel));
  // ... rest of function
}

After:

function em({ newState: A, oldState: B }) {
  if (B !== null && A.mainLoopModel !== B.mainLoopModel && A.mainLoopModel === null)
    HA1(null); // Removed m3("userSettings", { model: void 0 })
  if (B !== null && A.mainLoopModel !== B.mainLoopModel && A.mainLoopModel !== null)
    HA1(A.mainLoopModel); // Removed m3("userSettings", { model: A.mainLoopModel })
  // ... rest of function
}

Testing

Confirmed that after applying this fix:

  • Using /model to switch models only affects the current session
  • The settings.json file remains unchanged
  • Default model setting is preserved across sessions
  • Runtime model switching still works as expected

This fix ensures that /model behaves as a session-only command without side effects on persistent configuration.

View original on GitHub ↗

10 Comments

Koin-27 · 1 year ago

Update: This bug still exists in version 1.0.68

I can confirm this bug is still present in Claude Code version 1.0.68. The lL0 function in cli.js still uses
the hardcoded 32,000 token limit for all models.

Personal Impact:

  • Using Claude 4 Sonnet with 32k token truncation instead of the expected 64k
  • This significantly limits the usefulness of Sonnet for large code generation tasks

Fix Verification:
I've tested the proposed fix locally and can confirm it works perfectly:

  • ✅ Sonnet models now correctly support 64,000 tokens
  • ✅ Haiku models remain at 8,192 tokens
  • ✅ Opus models stay at 32,000 tokens
  • ✅ Error messages now show model-specific limits

Request:
Could this fix be prioritized for the next release? The solution is already provided and tested. Many users are
missing out on Sonnet's full 64k capacity.

Environment:

  • Claude CLI version: 1.0.68
  • OS: Windows 11
  • Model: Claude 4 Sonnet
salah9003 · 1 year ago
Update: This bug still exists in version 1.0.68 I can confirm this bug is still present in Claude Code version 1.0.68. The lL0 function in cli.js still uses the hardcoded 32,000 token limit for all models. Personal Impact: Using Claude 4 Sonnet with 32k token truncation instead of the expected 64k This significantly limits the usefulness of Sonnet for large code generation tasks Fix Verification: I've tested the proposed fix locally and can confirm it works perfectly: ✅ Sonnet models now correctly support 64,000 tokens ✅ Haiku models remain at 8,192 tokens ✅ Opus models stay at 32,000 tokens ✅ Error messages now show model-specific limits Request: Could this fix be prioritized for the next release? The solution is already provided and tested. Many users are missing out on Sonnet's full 64k capacity. Environment: Claude CLI version: 1.0.68 OS: Windows 11 * Model: Claude 4 Sonnet

Furthermore, theres a hardcoded limit of 21,333 tokens that overrides any higher max_tokens value in the settings.json. Even if you set max_tokens: 32000, the actual API requests will be capped at 21,333 tokens.

github-actions[bot] · 1 year ago

Found 1 possible duplicate issue:

  1. https://github.com/anthropics/claude-code/issues/4255

This issue will be automatically closed as a duplicate in 3 days.

  • If your issue is a duplicate, please close it and 👍 the existing issue instead
  • To prevent auto-closure, add a comment or 👎 this comment

🤖 Generated with Claude Code

KnowhereFern · 1 year ago

Confirming that this issue is still present on the latest version:

Error: Invalid env var CLAUDE_CODE_MAX_OUTPUT_TOKENS: 64000
at AL0 (file:///usr/local/lib/node_modules/@anthropic-ai/claude-code/cli.js:1875:28634)

And in the code section I see:

javascriptfunction AL0(A){
  if(A.includes("3-5"))return 8192;
  if(A.includes("haiku"))return 8192;
  let B=process.env.CLAUDE_CODE_MAX_OUTPUT_TOKENS;
  if(B){
    let Q=parseInt(B,10);
    if(!isNaN(Q)&&Q>0&&Q<=32000)return Q;
    else throw new Error(`Invalid env var CLAUDE_CODE_MAX_OUTPUT_TOKENS: ${B}`)
  }
  return 32000
}

The validation logic clearly shows:

It checks if the value is between 1 and 32,000 (Q>0&&Q<=32000)
if value of 64,000 exceeds this maximum
When the value is out of range, it throws the exact error

kierr · 11 months ago

@salah9003 I see this was closed and marked as completed 20 hours ago - is it resolved in 1.0.115? It's still hard-capped at 32K AFAIK?

salah9003 · 11 months ago

@kierr still capped at 32k. Probably to avoid bloating terminal with too much text

pmane · 11 months ago

why am i paying for max, it is disapointing

pmane · 11 months ago

is this related to tier ?

s3m1ck · 11 months ago

@shawnm-anthropic the problem is still happening in 1.0.119. Please provide guidance on how to work around or fix the issue.

github-actions[bot] · 11 months ago

This issue has been automatically locked since it was closed and has not had any activity for 7 days. If you're experiencing a similar issue, please file a new issue and reference this one if it's relevant.