Skip to main content
This site is an independent third-party technical service provider. Claude™ and Anthropic® are trademarks of Anthropic, PBC. This site has no affiliation, endorsement, or partnership with Anthropic.

LiteLLM + Claude API Troubleshooting Guide: Headers, Streaming, Routing, and MCP OAuth

A practical troubleshooting guide for running Claude API behind LiteLLM, covering header passthrough, streaming failures, model routing, MCP OAuth state, and production checks.

ToolsTroubleshooting GuideLiteLLMEst. read12min
2026.07.07 published
litellm-claude-api-anthropic-beta-streaming-model-routing-troubleshooting-2026

LiteLLM is a common open-source LLM gateway. Teams use it for unified routing, multiple API keys, usage visibility, and fallback policies. When Claude API sits behind LiteLLM, most failures fall into four categories:

  • headers are overwritten or dropped
  • streaming breaks or returns malformed chunks
  • model routing points to the wrong protocol or backend
  • MCP OAuth sessions lose state in multi-instance deployments

This guide is based on LiteLLM public documentation, community issue patterns, and common gateway-compatibility problems. LiteLLM behavior changes across versions, so treat every configuration detail here as something to verify against your installed version.

Start with the troubleshooting order

Do not begin by changing application code. Debug the layers in order.

1. Test ClaudeAPI directly

2. Test the same request through LiteLLM Proxy

3. Enable LiteLLM DEBUG logs and compare inbound/outbound headers and body

4. Check client SDK timeout, model name, and stream parsing

5. Check deployment state: multi-instance sessions, load balancing, shared storage
1. Test ClaudeAPI directly

2. Test the same request through LiteLLM Proxy

3. Enable LiteLLM DEBUG logs and compare inbound/outbound headers and body

4. Check client SDK timeout, model name, and stream parsing

5. Check deployment state: multi-instance sessions, load balancing, shared storage

This avoids a common mistake: seeing 400, 404, or stream interrupted and immediately rewriting business logic. Often, the backend Claude API path is healthy and the problem is in gateway conversion, header forwarding, timeout handling, or deployment state.

Minimal diagnosis matrix

Test path Result Likely conclusion
Direct https://gw.claudeapi.com works, LiteLLM fails Gateway-layer issue Check litellm_config.yaml, headers, provider prefix
Direct request also fails Backend request or key issue Check API key, model ID, request body, rate limits
Non-streaming works, streaming fails Long connection or SSE issue Check stream_timeout, proxy buffering, client parsing
Single instance works, multi-instance fails State-sharing issue Check Redis/session store, OAuth callback routing

Basic LiteLLM + Claude API architecture

Typical path:

Your app -> LiteLLM Proxy -> ClaudeAPI gateway -> Claude model
Your app -> LiteLLM Proxy -> ClaudeAPI gateway -> Claude model

LiteLLM usually handles:

  • protocol conversion between OpenAI-style and provider-native requests
  • header passthrough and rewriting
  • model routing
  • fallback and retries
  • optional session or gateway behavior for longer workflows

If any of those layers disagrees with what Claude API expects, you can see confusing errors.

Minimal configuration reference

This is a reference shape, not the only correct configuration:

# litellm_config.yaml
model_list:
  - model_name: claude-sonnet-4-6
    litellm_params:
      model: anthropic/claude-sonnet-4-6
      api_key: os.environ/CLAUDE_API_KEY
      api_base: https://gw.claudeapi.com
# litellm_config.yaml
model_list:
  - model_name: claude-sonnet-4-6
    litellm_params:
      model: anthropic/claude-sonnet-4-6
      api_key: os.environ/CLAUDE_API_KEY
      api_base: https://gw.claudeapi.com

If you use the direct Anthropic endpoint, the base URL would be Anthropic’s endpoint. This guide uses ClaudeAPI’s gateway:

https://gw.claudeapi.com
https://gw.claudeapi.com

Do not mix Anthropic-native and OpenAI-compatible paths

LiteLLM provider prefix and api_base must match the protocol.

Target protocol LiteLLM provider api_base Backend request style
Anthropic Messages API anthropic/claude-sonnet-5 https://gw.claudeapi.com /v1/messages
OpenAI-compatible Chat Completions openai/claude-sonnet-5 https://gw.claudeapi.com/v1 /v1/chat/completions

Common broken combinations:

  • model: anthropic/... with api_base ending in /v1
  • model: openai/... with an Anthropic Messages request body
  • client sends model: claude-sonnet-5, but LiteLLM only registered another alias

These often appear as:

  • 400 Bad Request
  • 404 model not found
  • malformed streaming events
  • provider-specific validation errors

Problem 1: anthropic-beta header is overwritten or dropped

Symptoms

  • beta features return 400
  • extended thinking, PDF parsing, or another beta behavior does not activate
  • direct backend requests work, but LiteLLM requests do not

Why it happens

When LiteLLM converts between protocols or reconstructs provider requests, headers may be filtered, overwritten, or not forwarded as expected. This is especially relevant for headers such as:

anthropic-beta
anthropic-version
x-api-key
anthropic-beta
anthropic-version
x-api-key

The exact behavior depends on LiteLLM version and provider implementation.

Step 1: confirm the direct request works

curl https://gw.claudeapi.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_CLAUDEAPI_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: extended-thinking-2025-01-01" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "test"}]
  }'
curl https://gw.claudeapi.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_CLAUDEAPI_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "anthropic-beta: extended-thinking-2025-01-01" \
  -d '{
    "model": "claude-sonnet-4-6",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "test"}]
  }'

If direct access works and LiteLLM fails, the gateway layer is the next place to inspect.

Step 2: check LiteLLM parameter handling

Review your LiteLLM settings. Some deployments use:

litellm_settings:
  drop_params: false
litellm_settings:
  drop_params: false

This setting is often used to avoid dropping parameters that LiteLLM does not recognize. It is not a complete security policy by itself. You still need safe key injection, log redaction, and version-specific validation.

Step 3: enable debug logs

export LITELLM_LOG="DEBUG"
export LITELLM_LOG="DEBUG"

Then search the logs for:

anthropic-beta
anthropic-version
x-api-key
anthropic-beta
anthropic-version
x-api-key

Check both:

  • inbound request headers received by LiteLLM
  • outbound request headers sent to the backend

Fix options

  • Confirm your LiteLLM version supports the beta header you need.
  • Use the correct provider prefix and protocol.
  • Avoid drop_params: true when beta parameters need to pass through.
  • Configure explicit extra headers if your LiteLLM version supports that path.
  • Temporarily test direct ClaudeAPI access to isolate LiteLLM from backend issues.

Problem 2: streaming is interrupted or malformed

Symptoms

  • stream=true starts normally and then breaks
  • client reports JSON decode error
  • client reports Incomplete chunked read
  • LiteLLM logs show connection reset or timeout

Likely layer

Layer Common cause
Client Timeout too short, SSE parsing bug, early connection close
LiteLLM gateway Buffering, timeout, stream conversion, proxy settings
Backend 429 rate limit, 529 overloaded, network reset

Step 1: test streaming without LiteLLM

curl https://gw.claudeapi.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_CLAUDEAPI_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-haiku-4-5-20251001",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Write a short poem."}],
    "stream": true
  }'
curl https://gw.claudeapi.com/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: YOUR_CLAUDEAPI_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -d '{
    "model": "claude-haiku-4-5-20251001",
    "max_tokens": 1024,
    "messages": [{"role": "user", "content": "Write a short poem."}],
    "stream": true
  }'

If direct streaming is stable but LiteLLM streaming breaks, focus on gateway timeout, buffering, and conversion.

Step 2: check LiteLLM timeouts

Exact settings vary by version, but deployments often tune values like:

litellm_settings:
  request_timeout: 600
  stream_timeout: 300
litellm_settings:
  request_timeout: 600
  stream_timeout: 300

Also check any reverse proxy in front of LiteLLM, such as Nginx, Cloudflare, ALB, API Gateway, or service mesh. Streaming often fails outside the application layer.

Step 3: verify client stream handling

Python example through LiteLLM:

import anthropic

client = anthropic.Anthropic(
    api_key="YOUR_PROXY_KEY",
    base_url="https://your-litellm-proxy.example.com",
)

with client.messages.stream(
    model="claude-haiku-4-5-20251001",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a short poem."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)
import anthropic

client = anthropic.Anthropic(
    api_key="YOUR_PROXY_KEY",
    base_url="https://your-litellm-proxy.example.com",
)

with client.messages.stream(
    model="claude-haiku-4-5-20251001",
    max_tokens=1024,
    messages=[{"role": "user", "content": "Write a short poem."}],
) as stream:
    for text in stream.text_stream:
        print(text, end="", flush=True)

Check:

  • the client points to LiteLLM, not direct ClaudeAPI
  • client timeout is longer than LiteLLM’s stream timeout
  • upstream proxies do not buffer or cut long responses
  • the client handles final stream events correctly

Problem 3: model routing causes 404 or 400

Symptoms

  • 404 model not found
  • 400 Bad Request
  • LiteLLM routes to the wrong backend
  • model alias does not match the request

LiteLLM has two model names:

  • model_name: the alias your application sends
  • litellm_params.model: the provider/model path LiteLLM uses internally

Check registered models

curl http://localhost:4000/v1/models
curl http://localhost:4000/v1/models

The response should include the model_name values defined in model_list.

Correct Anthropic-native routing

model_list:
  - model_name: claude-sonnet-5
    litellm_params:
      model: anthropic/claude-sonnet-5
      api_key: os.environ/CLAUDE_API_KEY
      api_base: https://gw.claudeapi.com
model_list:
  - model_name: claude-sonnet-5
    litellm_params:
      model: anthropic/claude-sonnet-5
      api_key: os.environ/CLAUDE_API_KEY
      api_base: https://gw.claudeapi.com

Then test through LiteLLM:

curl http://localhost:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-liteellm-proxy-key" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [{"role": "user", "content": "hi"}]
  }'
curl http://localhost:4000/v1/chat/completions \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer sk-liteellm-proxy-key" \
  -d '{
    "model": "claude-sonnet-5",
    "messages": [{"role": "user", "content": "hi"}]
  }'

If this returns 404, compare the request’s "model" value with model_list[].model_name.

Fix options

  • Use anthropic/ when the backend is Anthropic Messages API.
  • Use openai/ when the backend is OpenAI-compatible Chat Completions.
  • Pair anthropic/ with https://gw.claudeapi.com.
  • Pair openai/ with https://gw.claudeapi.com/v1.
  • Add aliases for clients that send different model names.

Problem 4: MCP OAuth session state is lost

Symptoms

  • 401 Unauthorized
  • Missing OAuth session state
  • first OAuth step succeeds but callback fails
  • sessions interfere across users or keys

Why it happens

MCP OAuth flows require server-side state, such as state, code verifier, and callback mapping.

In a LiteLLM or gateway deployment, state can be lost if:

  • multiple instances do not share session storage
  • load balancer sends callback to a different instance
  • headers or query parameters are rewritten
  • redirect_uri points to the wrong component
  • OAuth callback route is not mapped to the original session

What to check

  1. Deployment mode:
    • single instance: inspect local session behavior
    • multi-instance: use Redis or another shared session store if your deployment requires it
  2. Callback URL:
    • confirm redirect_uri points to the proxy callback endpoint when the proxy owns the flow
  3. State consistency:
    • compare state in authorization URL, callback, and LiteLLM logs
  4. Parameter filtering:
    • make sure state and OAuth parameters are not being dropped or renamed

Fix options

  • Use shared session storage for multi-instance deployments.
  • Keep OAuth callback routing sticky or state-aware.
  • Avoid filtering OAuth parameters.
  • Check LiteLLM version notes and MCP/OAuth documentation for current behavior.

General troubleshooting table

Error Most likely cause First place to check
401 Unauthorized API key or header passthrough problem Does outbound request include expected key/header?
404 model not found Model alias mismatch model_list.model_name vs request "model"
400 Bad Request Protocol mismatch anthropic/ vs openai/, and matching api_base
429 Rate Limit Backend rate limit Retry/fallback and key usage
529 Overloaded Model overload Fallback model and backoff
Streaming breaks Timeout or proxy buffering request_timeout, stream_timeout, reverse proxy
Missing OAuth session state Session state not shared Redis/session store and callback routing
Beta feature missing anthropic-beta lost drop_params, headers, debug logs

Production checklist

Before putting LiteLLM in production, run through this list.

Check Passing standard
API key injection Use environment variables or secret manager; no keys in Git
Protocol pairing anthropic/ with https://gw.claudeapi.com; openai/ with /v1
Header passthrough anthropic-beta, anthropic-version, and auth headers are not filtered
Streaming Both direct backend and LiteLLM streaming tests pass
Timeouts Client timeout > LiteLLM stream timeout; LiteLLM timeout > backend P95 latency
Multi-instance OAuth/MCP sessions use shared state where needed
Logs DEBUG only during troubleshooting; production logs redact keys
Rollback litellm_config.yaml is versioned and can be reverted quickly

The value of this checklist is moving from “it worked once” to “it survives streaming, concurrency, failover, and OAuth callbacks.”

FAQ

Should LiteLLM connect directly to Anthropic or to ClaudeAPI?

Both patterns can work. Choose based on account, billing, network, operations, and compliance needs. If using ClaudeAPI, configure the gateway URL shown in the ClaudeAPI console. If using Anthropic directly, follow Anthropic’s official endpoint and credential docs.

Is drop_params: false unsafe?

Not by itself. It controls whether LiteLLM drops unsupported or unknown parameters. It does not replace key management, log redaction, or explicit allowlists. Use it intentionally and validate what reaches the backend.

Is every streaming issue a LiteLLM issue?

No. Test direct backend streaming first. If direct streaming fails, investigate backend, rate limit, or network. If direct works and LiteLLM fails, focus on gateway timeouts, buffering, and conversion.

What is the difference between anthropic/claude-sonnet-5 and openai/claude-sonnet-5?

anthropic/ means LiteLLM should use Anthropic-style Messages API behavior. openai/ means it should use OpenAI-compatible Chat Completions behavior. ClaudeAPI supports both access styles, but the provider prefix determines how LiteLLM constructs the request.

How do I see the actual headers LiteLLM sends?

Enable debug logs:

export LITELLM_LOG="DEBUG"
export LITELLM_LOG="DEBUG"

Then make a request and inspect the outbound request in logs. If logs are not enough, use a local HTTP debugging proxy only in a controlled non-production environment. Never expose API keys in shared logs.

Do I need to restart LiteLLM after config changes?

It depends on deployment method and parameter type. If you start LiteLLM from a config file, many changes require restart. Some UI or dynamic configuration paths may support hot updates. Check your LiteLLM version documentation.

Sources

ClaudeAPI is an independent third-party technical service provider. It is not affiliated with Anthropic and does not guarantee the availability of Anthropic services.

Related Articles