litellm - ✅(Solved) Fix [Bug]: effort="max" hardcoded as Opus 4.6 only — Opus 4.7 rejected even though Anthropic API accepts it [1 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
BerriAI/litellm#25957Fetched 2026-04-18 05:52:50
View on GitHub
Comments
1
Participants
2
Timeline
7
Reactions
1
Timeline (top)
labeled ×2referenced ×2commented ×1cross-referenced ×1

Error Message

ValueError: effort='max' is only supported by Claude Opus 4.6. Got model: anthropic/claude-opus-4-7-20260408

Root Cause

Anyone trying to drive Opus 4.7 at effort=max through LiteLLM (proxy or SDK) — including Claude Code via the ANTHROPIC_BASE_URL workflow — gets a hard 4xx and has to either downgrade the request to effort=high or hand-patch LiteLLM. There's no model-map override that bypasses the check because the gate is hardcoded to _is_opus_4_6_model.

Fix Action

Fix / Workaround

Anyone trying to drive Opus 4.7 at effort=max through LiteLLM (proxy or SDK) — including Claude Code via the ANTHROPIC_BASE_URL workflow — gets a hard 4xx and has to either downgrade the request to effort=high or hand-patch LiteLLM. There's no model-map override that bypasses the check because the gate is hardcoded to _is_opus_4_6_model.

PR fix notes

PR #25958: fix(anthropic): allow effort="max" on Claude Opus 4.7

Description (problem / solution / changelog)

Title

fix(anthropic): allow effort="max" on Claude Opus 4.7

Relevant issues

Fixes #25957

Pre-Submission Checklist (Click to expand)

  • I have Read the Contributing Guide
  • I have added a test for this PR
  • My PR passes all unit tests on make test-unit
  • My PR's scope is as isolated as possible

Type

🐛 Bug Fix

Changes

AnthropicConfig._apply_output_config previously rejected effort="max" for any model that wasn't Claude Opus 4.6:

# litellm/llms/anthropic/chat/transformation.py (before)
# ``max`` is Claude Opus 4.6 only (not Sonnet 4.6, not Opus 4.5/4.7).
# Keep this hardcoded so the error message is specific and stable.
if effort == "max" and not self._is_opus_4_6_model(model):
    raise ValueError(
        f"effort='max' is only supported by Claude Opus 4.6. "
        f"Got model: {model}"
    )

This guard was added in #22234 (back when 4.6 was the only model accepting max) and was intentionally kept in the day-0 4.7 PR (#25867). However, Anthropic's Messages API accepts output_config.effort="max" on claude-opus-4-7-* as well — calling the API directly with model=claude-opus-4-7-*, output_config={"effort":"max"}, and thinking={"type":"adaptive"} returns a normal 200 completion.

So LiteLLM was the only thing in the chain rejecting a perfectly valid configuration, breaking flows like Claude Code via ANTHROPIC_BASE_URL and any direct SDK call against Opus 4.7 with reasoning_effort="max".

This PR allows effort="max" on both Opus 4.6 and Opus 4.7. _is_opus_4_7_model already exists on AnthropicConfig (added in #25867), so the diff is minimal:

if effort == "max" and not (
    self._is_opus_4_6_model(model) or self._is_opus_4_7_model(model)
):
    raise ValueError(
        f"effort='max' is only supported by Claude Opus 4.6 and 4.7. "
        f"Got model: {model}"
    )

I kept the substring-style check (rather than switching to a model-map supports_max_reasoning_effort lookup) so date-variant model names (e.g. claude-opus-4-7-20260408) keep working without requiring every dated entry to be present in the cost map. Switching to a data-driven lookup would be a reasonable follow-up but is out of scope for this fix.

Tests

  • Updated test_max_effort_rejected_for_opus_45 and test_max_effort_rejected_for_sonnet_46 to match the new error message.
  • Added test_max_effort_accepted_for_opus_47 (regression for #25957).
  • Existing test_max_effort_accepted_for_opus_46 still passes unchanged.
$ pytest tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py -k "effort or output_config or opus"
......................                                                   [100%]
22 passed, 115 deselected in 0.32s

Changed files

  • litellm/llms/anthropic/chat/transformation.py (modified, +8/-7)
  • litellm/model_prices_and_context_window_backup.json (modified, +28/-9)
  • litellm/types/utils.py (modified, +1/-0)
  • litellm/utils.py (modified, +3/-0)
  • model_prices_and_context_window.json (modified, +28/-9)
  • tests/test_litellm/llms/anthropic/chat/test_anthropic_chat_transformation.py (modified, +54/-14)
  • uv.lock (modified, +1/-1)

Code Example

# litellm/llms/anthropic/chat/transformation.py (main, c0fc4c4)
# ``max`` is Claude Opus 4.6 only (not Sonnet 4.6, not Opus 4.5/4.7).
# Keep this hardcoded so the error message is specific and stable.
if effort == "max" and not self._is_opus_4_6_model(model):
    raise ValueError(
        f"effort='max' is only supported by Claude Opus 4.6. "
        f"Got model: {model}"
    )

---

import litellm

resp = litellm.completion(
    model="anthropic/claude-opus-4-7-20260408",
    messages=[{"role": "user", "content": "hi"}],
    reasoning_effort="max",
)

---

ValueError: effort='max' is only supported by Claude Opus 4.6. Got model: anthropic/claude-opus-4-7-20260408

---

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-4-7-20260408",
    "max_tokens": 1024,
    "thinking": {"type": "adaptive"},
    "output_config": {"effort": "max"},
    "messages": [{"role":"user","content":"hi"}]
  }'
# → 200 OK
RAW_BUFFERClick to expand / collapse

Check for existing issues

  • I have searched the existing issues and checked that my issue is not a duplicate.

What happened?

effort="max" is hardcoded as Opus 4.6 only in AnthropicConfig._apply_output_config, so any request that targets Claude Opus 4.7 with reasoning_effort="max" (or output_config.effort="max") is rejected by LiteLLM before it ever reaches the Anthropic API:

# litellm/llms/anthropic/chat/transformation.py (main, c0fc4c4)
# ``max`` is Claude Opus 4.6 only (not Sonnet 4.6, not Opus 4.5/4.7).
# Keep this hardcoded so the error message is specific and stable.
if effort == "max" and not self._is_opus_4_6_model(model):
    raise ValueError(
        f"effort='max' is only supported by Claude Opus 4.6. "
        f"Got model: {model}"
    )

This guard was added in #22234 (back when 4.6 was the only model that accepted max) and was intentionally kept in the day-0 4.7 PR (#25867). However, Anthropic's Claude API accepts output_config.effort="max" on claude-opus-4-7-* as well — calling the Anthropic Messages API directly with model=claude-opus-4-7-20260408 + output_config={"effort":"max"} + thinking={"type":"adaptive"} succeeds and returns a normal completion.

So LiteLLM is the only thing in the chain rejecting a perfectly valid configuration.

Reproduce

LiteLLM v1.83.3-stable.opus-4.7 (also reproduces on main at c0fc4c4):

import litellm

resp = litellm.completion(
    model="anthropic/claude-opus-4-7-20260408",
    messages=[{"role": "user", "content": "hi"}],
    reasoning_effort="max",
)

Result:

ValueError: effort='max' is only supported by Claude Opus 4.6. Got model: anthropic/claude-opus-4-7-20260408

Same request hitting Anthropic directly (bypassing LiteLLM):

curl https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{
    "model": "claude-opus-4-7-20260408",
    "max_tokens": 1024,
    "thinking": {"type": "adaptive"},
    "output_config": {"effort": "max"},
    "messages": [{"role":"user","content":"hi"}]
  }'
# → 200 OK

Also reproduces via Vertex (anthropic-vertex/claude-opus-4-7@*) and Bedrock (bedrock/anthropic.claude-opus-4-7-*).

Impact

Anyone trying to drive Opus 4.7 at effort=max through LiteLLM (proxy or SDK) — including Claude Code via the ANTHROPIC_BASE_URL workflow — gets a hard 4xx and has to either downgrade the request to effort=high or hand-patch LiteLLM. There's no model-map override that bypasses the check because the gate is hardcoded to _is_opus_4_6_model.

Suggested fix

Replace the hardcoded _is_opus_4_6_model gate with a model-map lookup (supports_max_reasoning_effort), the same data-driven pattern already used for xhigh. That way enabling max on a new model is a pure model-map change and we never have to ship a code change again when a future Opus model adds max support.

Minimal code-only fallback (if the model-map change is preferred as a follow-up): also accept _is_opus_4_7_model(model) in the effort == "max" guard. Both _is_opus_4_6_model and _is_opus_4_7_model already exist on AnthropicConfig.

Happy to send a PR — let me know which shape you'd prefer.

Are you a ML Ops Team?

No

What LiteLLM version are you on?

v1.83.3-stable.opus-4.7 (also reproduced against main @ c0fc4c4)

Twitter / LinkedIn details

No response

extent analysis

TL;DR

Update the effort == "max" guard in AnthropicConfig._apply_output_config to support Opus 4.7 models by using a model-map lookup or adding a check for _is_opus_4_7_model.

Guidance

  • Identify the hardcoded model check in transformation.py and consider replacing it with a data-driven approach using a model-map lookup.
  • As a minimal fallback, update the existing guard to also accept _is_opus_4_7_model(model) for Opus 4.7 models.
  • Verify the fix by testing the litellm.completion function with reasoning_effort="max" and an Opus 4.7 model.
  • Consider sending a PR with the suggested fix to update the LiteLLM codebase.

Example

# Update the effort == "max" guard to support Opus 4.7 models
if effort == "max" and not (self._is_opus_4_6_model(model) or self._is_opus_4_7_model(model)):
    raise ValueError(
        f"effort='max' is only supported by Claude Opus 4.6 and 4.7. "
        f"Got model: {model}"
    )

Notes

The suggested fix assumes that the _is_opus_4_7_model function is already implemented and available in the AnthropicConfig class. If this is not the case, additional implementation may be required.

Recommendation

Apply the workaround by updating the effort == "max" guard to support Opus 4.7 models, as this will allow users to drive Opus 4.7 at effort=max through LiteLLM without requiring a code change for future models.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

litellm - ✅(Solved) Fix [Bug]: effort="max" hardcoded as Opus 4.6 only — Opus 4.7 rejected even though Anthropic API accepts it [1 pull requests, 1 comments, 2 participants]