Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
305 changes: 103 additions & 202 deletions docs/my-website/blog/claude_code_beta_headers/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
---
slug: claude_code_beta_headers
title: "Claude Code - Managing Anthropic Beta Headers"
slug: claude-code-beta-headers-incident
title: "Incident Report: Invalid beta headers with Claude Code"
date: 2026-02-16T10:00:00
authors:
- name: Sameer Kankute
Expand All @@ -15,260 +15,161 @@ authors:
title: "CEO, LiteLLM"
url: https://www.linkedin.com/in/krish-d/
image_url: https://pbs.twimg.com/profile_images/1298587542745358340/DZv3Oj-h_400x400.jpg
description: "How to manage and configure Anthropic beta headers with Claude Code in LiteLLM: filtering, mapping, and dynamic updates across providers."
tags: [anthropic, claude, beta headers, configuration, liteLLM]
tags: [incident-report, anthropic, stability]
hide_table_of_contents: false

---
import Image from '@theme/IdealImage';

When using Claude Code with LiteLLM and non-Anthropic providers (Bedrock, Azure AI, Vertex AI), you need to ensure that only supported beta headers are sent to each provider. This guide explains how to add support for new beta headers or fix invalid beta header errors.

## What Are Beta Headers?

Anthropic uses beta headers to enable experimental features in Claude. When you use Claude Code, it may send beta headers like:

```
anthropic-beta: prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20
```

However, not all providers support all Anthropic beta features. LiteLLM uses `anthropic_beta_headers_config.json` to manage which beta headers are supported by each provider.

## Common Error Message
**Date:** February 13, 2026
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent incident date

The incident date listed here is "February 13, 2026", but the timeline section (lines 71-75) places all events on February 15-16, 2026. These dates should be reconciled β€” either the header date should be updated to February 15, or the timeline dates need correcting.

**Duration:** ~3 hours
**Severity:** High
**Status:** Resolved

```bash
Error: The model returned the following errors: invalid beta flag
```

## How LiteLLM Handles Beta Headers

LiteLLM uses a strict validation approach with a configuration file:

```
litellm/litellm/anthropic_beta_headers_config.json
```
## Summary

This JSON file contains a **mapping** of beta headers for each provider:
- **Keys**: Input beta header names (from Anthropic)
- **Values**: Provider-specific header names (or `null` if unsupported)
- **Validation**: Only headers present in the mapping with non-null values are forwarded

This enforces stricter validation than just filtering unsupported headers - headers must be explicitly defined to be allowed.

## Adding Support for a New Beta Header

When Anthropic releases a new beta feature, you need to add it to the configuration file for each provider.

### Step 1: Add the New Beta Header

Open `anthropic_beta_headers_config.json` and add the new header to each provider's mapping:

```json title="anthropic_beta_headers_config.json"
{
"description": "Mapping of Anthropic beta headers for each provider. Keys are input header names, values are provider-specific header names (or null if unsupported). Only headers present in mapping keys with non-null values can be forwarded.",
"anthropic": {
"advanced-tool-use-2025-11-20": "advanced-tool-use-2025-11-20",
"new-feature-2026-03-01": "new-feature-2026-03-01",
...
},
"azure_ai": {
"advanced-tool-use-2025-11-20": "advanced-tool-use-2025-11-20",
"new-feature-2026-03-01": "new-feature-2026-03-01",
...
},
"bedrock_converse": {
"advanced-tool-use-2025-11-20": "tool-search-tool-2025-10-19",
"new-feature-2026-03-01": null,
...
},
"bedrock": {
"advanced-tool-use-2025-11-20": "tool-search-tool-2025-10-19",
"new-feature-2026-03-01": null,
...
},
"vertex_ai": {
"advanced-tool-use-2025-11-20": "tool-search-tool-2025-10-19",
"new-feature-2026-03-01": null,
...
}
}
```

**Key Points:**
- **Supported headers**: Set the value to the provider-specific header name (often the same as the key)
- **Unsupported headers**: Set the value to `null`
- **Header transformations**: Some providers use different header names (e.g., Bedrock maps `advanced-tool-use-2025-11-20` to `tool-search-tool-2025-10-19`)
- **Alphabetical order**: Keep headers sorted alphabetically for maintainability

### Step 2: Reload Configuration (No Restart Required!)

**Option 1: Dynamic Reload Without Restart**

Instead of restarting your application, you can dynamically reload the beta headers configuration using environment variables and API endpoints:

```bash
# Set environment variable to fetch from remote URL (Do this if you want to point it to some other URL)
export LITELLM_ANTHROPIC_BETA_HEADERS_URL="https://raw.githubusercontent.com/BerriAI/litellm/main/litellm/anthropic_beta_headers_config.json"

# Manually trigger reload via API (no restart needed!)
curl -X POST "https://your-proxy-url/reload/anthropic_beta_headers" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```

**Option 2: Schedule Automatic Reloads**

Set up automatic reloading to always stay up-to-date with the latest beta headers:

```bash
# Reload configuration every 24 hours
curl -X POST "https://your-proxy-url/schedule/anthropic_beta_headers_reload?hours=24" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```

**Option 3: Traditional Restart**

If you prefer the traditional approach, restart your LiteLLM proxy or application:

```bash
# If using LiteLLM proxy
litellm --config config.yaml

# If using Python SDK
# Just restart your Python application
```
Claude Code began sending unsupported Anthropic beta headers to non-Anthropic providers (Bedrock, Azure AI, Vertex AI), causing `invalid beta flag` errors. LiteLLM was forwarding all beta headers without provider-specific validation. Users experienced request failures when routing Claude Code requests through LiteLLM to these providers.

:::tip Zero-Downtime Updates
With dynamic reloading, you can fix invalid beta header errors **without restarting your service**! This is especially useful in production environments where downtime is costly.
- **LLM calls to Anthropic:** No impact.
- **LLM calls to Bedrock/Azure/Vertex:** Failed with `invalid beta flag` errors when unsupported headers were present.
- **Cost tracking and routing:** No impact.

See [Auto Sync Anthropic Beta Headers](../proxy/sync_anthropic_beta_headers.md) for complete documentation.
:::
{/* truncate */}

## Fixing Invalid Beta Header Errors
---

If you encounter an "invalid beta flag" error, it means a beta header is being sent that the provider doesn't support.
## Background

### Step 1: Identify the Problematic Header
Anthropic uses beta headers to enable experimental features in Claude. When Claude Code makes API requests, it includes headers like `anthropic-beta: prompt-caching-scope-2026-01-05,advanced-tool-use-2025-11-20`. However, not all providers support all Anthropic beta features.

Check your logs to see which header is causing the issue:
Before this incident, LiteLLM forwarded all beta headers to all providers without validation:

```bash
Error: The model returned the following errors: invalid beta flag: new-feature-2026-03-01
```
```mermaid
sequenceDiagram
participant CC as Claude Code
participant LP as LiteLLM (old behavior)
participant Provider as Provider (Bedrock/Azure/Vertex)

### Step 2: Update the Config
CC->>LP: Request with beta headers
Note over CC,LP: anthropic-beta: header1,header2,header3

Set the header value to `null` for that provider:
LP->>Provider: Forward ALL headers (no validation)
Note over LP,Provider: anthropic-beta: header1,header2,header3

```json title="anthropic_beta_headers_config.json"
{
"bedrock_converse": {
"new-feature-2026-03-01": null
}
}
Provider-->>LP: ❌ Error: invalid beta flag
LP-->>CC: Request fails
```

### Step 3: Restart and Test

Restart your application and verify the header is now filtered out.

## Contributing a Fix to LiteLLM
Requests succeeded for Anthropic (native support) but failed for other providers when Claude Code sent headers those providers didn't support.

Help the community by contributing your fix!

### What to Include in Your PR

1. **Update the config file**: Add the new beta header to `litellm/anthropic_beta_headers_config.json`
2. **Test your changes**: Verify the header is correctly filtered/mapped for each provider
3. **Documentation**: Include provider documentation links showing which headers are supported

### Example PR Description

```markdown
## Add support for new-feature-2026-03-01 beta header
---

### Changes
- Added `new-feature-2026-03-01` to anthropic_beta_headers_config.json
- Set to `null` for bedrock_converse (unsupported)
- Set to header name for anthropic, azure_ai (supported)
## Root cause

### Testing
Tested with:
- βœ… Anthropic: Header passed through correctly
- βœ… Azure AI: Header passed through correctly
- βœ… Bedrock Converse: Header filtered out (returns error without fix)
LiteLLM lacked provider-specific beta header validation. When Claude Code introduced new beta features or sent headers that specific providers didn't support, those headers were blindly forwarded, causing provider API errors.

### References
- Anthropic docs: [link]
- AWS Bedrock docs: [link]
```
---

## Remediation

## How Beta Header Filtering Works
| # | Action | Status | Code |
|---|---|---|---|
| 1 | Create `anthropic_beta_headers_config.json` with provider-specific mappings | βœ… Done | [`anthropic_beta_headers_config.json`](https://github.com/BerriAI/litellm/blob/main/litellm/anthropic_beta_headers_config.json) |
| 2 | Implement strict validation: headers must be explicitly mapped to be forwarded | βœ… Done | [`litellm_logging.py`](https://github.com/BerriAI/litellm/blob/main/litellm/litellm_core_utils/litellm_logging.py) |
| 3 | Add `/reload/anthropic_beta_headers` endpoint for dynamic config updates | βœ… Done | Proxy management endpoints |
| 4 | Add `/schedule/anthropic_beta_headers_reload` for automatic periodic updates | βœ… Done | Proxy management endpoints |
| 5 | Support `LITELLM_ANTHROPIC_BETA_HEADERS_URL` for custom config sources | βœ… Done | Environment configuration |
| 6 | Support `LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS` for air-gapped deployments | βœ… Done | Environment configuration |

When you make a request through LiteLLM:
Now LiteLLM validates and transforms headers per-provider:

```mermaid
sequenceDiagram
participant CC as Claude Code
participant LP as LiteLLM
participant LP as LiteLLM (new behavior)
participant Config as Beta Headers Config
participant Provider as Provider (Bedrock/Azure/etc)
participant Provider as Provider (Bedrock/Azure/Vertex)

CC->>LP: Request with beta headers
Note over CC,LP: anthropic-beta: header1,header2,header3

LP->>Config: Load header mapping for provider
Config-->>LP: Returns mapping (header→value or null)

Note over LP: Validate & Transform:<br/>1. Check if header exists in mapping<br/>2. Filter out null values<br/>3. Map to provider-specific names

LP->>Provider: Request with filtered & mapped headers
Note over LP,Provider: anthropic-beta: mapped-header2<br/>(header1, header3 filtered out)
Provider-->>LP: Success response

Provider-->>LP: βœ… Success response
LP-->>CC: Response
```

### Filtering Rules
---

1. **Header must exist in mapping**: Unknown headers are filtered out
2. **Header must have non-null value**: Headers with `null` values are filtered out
3. **Header transformation**: Headers are mapped to provider-specific names (e.g., `advanced-tool-use-2025-11-20` β†’ `tool-search-tool-2025-10-19` for Bedrock)
## Dynamic configuration updates

### Example
A key improvement is zero-downtime configuration updates. When Anthropic releases new beta features, users can update their configuration without restarting:

Request with headers:
```
anthropic-beta: advanced-tool-use-2025-11-20,computer-use-2025-01-24,unknown-header
```bash
# Manually trigger reload (no restart needed)
curl -X POST "https://your-proxy-url/reload/anthropic_beta_headers" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"

# Or schedule automatic reloads every 24 hours
curl -X POST "https://your-proxy-url/schedule/anthropic_beta_headers_reload?hours=24" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```

For Bedrock Converse:
- βœ… `computer-use-2025-01-24` β†’ `computer-use-2025-01-24` (supported, passed through)
- ❌ `advanced-tool-use-2025-11-20` β†’ filtered out (null value in config)
- ❌ `unknown-header` β†’ filtered out (not in config)
This prevents future incidents where Claude Code introduces new headers before LiteLLM configuration is updated.

Result sent to Bedrock:
```
anthropic-beta: computer-use-2025-01-24
---

## Configuration format

The `anthropic_beta_headers_config.json` file maps input headers to provider-specific output headers:

```json
{
"description": "Mapping of Anthropic beta headers for each provider.",
"anthropic": {
"advanced-tool-use-2025-11-20": "advanced-tool-use-2025-11-20",
"computer-use-2025-01-24": "computer-use-2025-01-24"
},
"bedrock_converse": {
"advanced-tool-use-2025-11-20": null,
"computer-use-2025-01-24": "computer-use-2025-01-24"
},
"azure_ai": {
"advanced-tool-use-2025-11-20": "advanced-tool-use-2025-11-20",
"computer-use-2025-01-24": "computer-use-2025-01-24"
}
}
```

## Dynamic Configuration Management (No Restart Required!)
**Validation rules:**
1. Headers must exist in the mapping for the target provider
2. Headers with `null` values are filtered out (unsupported)
3. Header names can be transformed per-provider (e.g., Bedrock uses different names for some features)

### Environment Variables
---

Control how LiteLLM loads the beta headers configuration:
## Resolution steps for users

| Variable | Description | Default |
|----------|-------------|---------|
| `LITELLM_ANTHROPIC_BETA_HEADERS_URL` | URL to fetch config from | GitHub main branch |
| `LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS` | Set to `True` to use local config only | `False` |
For users still experiencing issues, update to the latest LiteLLM version if < v1.81.11-nightly:

**Example: Use Custom Config URL**
```bash
export LITELLM_ANTHROPIC_BETA_HEADERS_URL="https://your-company.com/custom-beta-headers.json"
pip install --upgrade litellm
```

**Example: Use Local Config Only (No Remote Fetching)**
Or manually reload the configuration without restarting:

```bash
export LITELLM_LOCAL_ANTHROPIC_BETA_HEADERS=True
curl -X POST "https://your-proxy-url/reload/anthropic_beta_headers" \
-H "Authorization: Bearer YOUR_ADMIN_TOKEN"
```

---

## Related documentation

- [Managing Anthropic Beta Headers](../proxy/sync_anthropic_beta_headers.md) - Complete configuration guide
- [`anthropic_beta_headers_config.json`](https://github.com/BerriAI/litellm/blob/main/litellm/anthropic_beta_headers_config.json) - Current configuration file
Loading