Skip to content

[Bug]: Thinking blocks silently dropped in main chat/completions path when thinking key is null/missing #24026

@VascoSch92

Description

@VascoSch92

Check for existing issues

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

What happened?

Thinking blocks from Anthropic extended thinking responses are silently dropped in the main /chat/completions code path when the thinking key is null or missing from the content block, even though the block has "type": "thinking".

This causes empty responses being returned to clients (no content, no tool_calls, no thinking_blocks)

Root Cause

In litellm/llms/anthropic/chat/transformation.py line 1525, thinking blocks are detected by checking if the thinking value is not None:

elif content.get("thinking", None) is not None:  # ❌ WRONG

But they should be detected by checking if the type field equals "thinking" (like the fixed experimental pass-through path):

elif content.get("type") == "thinking":  # ✅ CORRECT

Why this matters

When Anthropic returns a thinking block like:

{"type": "thinking", "thinking": null, "signature": "..."}

The current check content.get("thinking", None) is not None evaluates to False, so the block is silently dropped.
PR #15501 fixed one path but not the other

PR #15501 correctly fixed litellm/llms/anthropic/experimental_pass_through/adapters/transformation.py (line 609):

elif content.get("type") == "thinking":  # ✅ Fixed

But the main chat path in litellm/llms/anthropic/chat/transformation.py (line 1525) was NOT updated:

elif content.get("thinking", None) is not None:  # ❌ Still buggy

Steps to Reproduce

A minimal script to reproduce

"""Reproduction: thinking blocks with null/missing 'thinking' key are silently dropped."""

from litellm.llms.anthropic.chat.transformation import AnthropicConfig

config = AnthropicConfig()

responses = {
    "thinking=text": {"content": [{"type": "thinking", "thinking": "some text", "signature": "s"}]},
    "thinking=None": {"content": [{"type": "thinking", "thinking": None, "signature": "s"}]},
    "thinking missing": {"content": [{"type": "thinking", "signature": "s"}]},
}

for name, response in responses.items():
    result = config.extract_response_content(completion_response=response)
    thinking_blocks = result[2]  # third return value
    print(f"{name:20} -> thinking_blocks: {thinking_blocks}")

Relevant log output

What part of LiteLLM is this about?

SDK (litellm Python package)

What LiteLLM version are you on ?

v1.82.4

Twitter / LinkedIn details

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions