BerriAI/litellm · error · AnthropicError

Invalid reasoning_effort: {reasoning_effort!r}. Must be one

Error message

Invalid reasoning_effort: {reasoning_effort!r}. Must be one of: 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'none'

What it means

Raised during translation of reasoning_effort for Anthropic models with adaptive thinking (output_config). The requested reasoning_effort string is mapped through REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT; for adaptive-thinking models an unmapped effort value (not in minimal/low/medium/high/xhigh/max/none) is a hard 400 AnthropicError, not a silent drop.

Source

Thrown at litellm/llms/anthropic/experimental_pass_through/messages/transformation.py:296

        try:
            mapped_thinking: Final = AnthropicConfig._map_reasoning_effort(
                reasoning_effort=reasoning_effort,
                model=model,
                custom_llm_provider=custom_llm_provider,
            )
        except _BadRequestError as e:
            raise AnthropicError(message=str(e.message), status_code=400)

        if mapped_thinking is None:
            optional_params.pop("thinking", None)
            optional_params.pop("output_config", None)
            return

        optional_params.setdefault("thinking", mapped_thinking)
        if AnthropicModelInfo._is_adaptive_thinking_model(model, custom_llm_provider):
            mapped_effort: Final = REASONING_EFFORT_TO_OUTPUT_CONFIG_EFFORT.get(reasoning_effort)
            if mapped_effort is None:
                raise AnthropicError(
                    message=(
                        f"Invalid reasoning_effort: {reasoning_effort!r}. "
                        f"Must be one of: 'minimal', 'low', 'medium', 'high', "
                        f"'xhigh', 'max', 'none'"
                    ),
                    status_code=400,
                )
            gate_error: Final = AnthropicConfig._validate_effort_for_model(model, mapped_effort, custom_llm_provider)
            if gate_error is not None:
                raise AnthropicError(message=gate_error, status_code=400)
            existing_output_config = optional_params.get("output_config")
            if not isinstance(existing_output_config, dict):
                existing_output_config = {}
            existing_output_config.setdefault("effort", mapped_effort)
            optional_params["output_config"] = existing_output_config

    @staticmethod
    def _translate_legacy_thinking_for_adaptive_model(

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Use one of: 'minimal', 'low', 'medium', 'high', 'xhigh', 'max', 'none'.
  2. If a newer effort level seems legitimate, upgrade litellm so the mapping table includes it.
  3. Pass the plain string, not an enum instance, as reasoning_effort.

Example fix

# before
response = litellm.completion(model="anthropic/adaptive-model", reasoning_effort="extreme", ...)

# after
response = litellm.completion(model="anthropic/adaptive-model", reasoning_effort="high", ...)
Defensive patterns

Strategy: type-guard

Validate before calling

VALID_REASONING_EFFORTS = {"minimal", "low", "medium", "high", "xhigh", "max", "none"}

def validate_reasoning_effort(effort: str) -> None:
    if effort not in VALID_REASONING_EFFORTS:
        raise ValueError(f"reasoning_effort must be one of {sorted(VALID_REASONING_EFFORTS)}")

Type guard

def is_valid_reasoning_effort(effort: object) -> bool:
    return isinstance(effort, str) and effort in {
        "minimal", "low", "medium", "high", "xhigh", "max", "none"
    }

Try / catch

try:
    resp = litellm.completion(model=model, reasoning_effort=effort, ...)
except Exception as e:
    if "Invalid reasoning_effort" in str(e):
        resp = litellm.completion(model=model, reasoning_effort="medium", ...)
    else:
        raise

Prevention

When it happens

Trigger: Calling an adaptive-thinking Anthropic model (e.g. one whose model info sets adaptive thinking) with reasoning_effort='extreme' or any string outside the seven allowed values. Non-adaptive models tolerate unknown efforts (thinking is popped), but adaptive models raise here.

Common situations: Reasoning-effort strings from other SDKs (OpenRouter 'effort' values, custom 'ultra'); version mismatch where an older litellm does not know a newly added effort level; passing the enum object instead of its string value (mapped lookup misses).

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/8b3655d55bf83ed1. Report an issue: GitHub.