CLAUDE_CODE_ATTRIBUTION_HEADER: Fix Bedrock 400 Errors & Prompt Caching Issues#
Published on March 18, 2026
CLAUDE_CODE_ATTRIBUTION_HEADER controls whether Claude Code injects the x-anthropic-billing-header into API requests. Setting it to 0 fixes two common problems: Bedrock 400 errors caused by the billing header in system prompts, and broken prompt caching when using proxies like claude-code-router or liteLLM. This guide covers exactly what the env var does, the bugs it fixes, and how to set it — plus the critical distinction between this env var and the separate attribution git settings.
What CLAUDE_CODE_ATTRIBUTION_HEADER Does#
Starting in Claude Code v2.1.29, every API request includes an x-anthropic-billing-header injected into the system prompt. This header contains metadata like:
x-anthropic-billing-header: cc_version=2.1.38; cc_entrypoint=cli; cch=4873d;
This billing header serves Anthropic's internal analytics — it tells them which Claude Code version and entrypoint (CLI, VS Code, GitHub Action) generated the request. It has nothing to do with git commit attribution.
When you set CLAUDE_CODE_ATTRIBUTION_HEADER=0, this billing header is suppressed entirely.
Problem 1: Bedrock 400 Errors#
The Bug#
When using Claude Code with AWS Bedrock (via CLAUDE_CODE_USE_BEDROCK=1), the billing header is injected as a text block in the system prompt content array. Bedrock's API validates system prompt content and rejects x-anthropic-billing-header as a reserved keyword:
ValidationException: x-anthropic-billing-header is a reserved keyword
and may not be used in the system prompt
This error is intermittent — the billing header hash (cch=) changes between requests, and not every request triggers the rejection. Typically the first request (token-counting call to Haiku) succeeds, while the main model request fails.
Affected Versions#
- Introduced: v2.1.29 (when the billing header was first added)
- Affected: v2.1.29 through v2.1.37
- Fixed: v2.1.39 (Anthropic stopped injecting the header into Bedrock system prompts)
The Fix#
If you're on an affected version, set:
export CLAUDE_CODE_ATTRIBUTION_HEADER=0
If you're on v2.1.39+, the Bedrock-specific bug is resolved — but you may still want to disable it for prompt caching reasons (see below).
References: GitHub #24168 (main bug report), claude-code-action #928 (same bug in GitHub Actions)
Problem 2: Prompt Caching Breakage with Proxies#
The Bug#
The billing header changes on every request (the cch= hash is dynamic). When you route Claude Code through a proxy like claude-code-router, liteLLM, or a custom API gateway, this dynamic header breaks prompt caching.
Prompt caching works by matching the system prompt prefix between requests. If the billing header changes every time, the cache key changes, and every request is a cache miss. This means:
- Higher latency (no cached prefix)
- Higher costs (full token processing on every request)
- Reduced throughput
Who's Affected#
Anyone running Claude Code through:
- claude-code-router — PR #1220 documents the fix
- liteLLM — Prompt cache routing docs mention this issue
- Custom API proxies using
ANTHROPIC_BASE_URL - Cost-tracking middleware that sits between Claude Code and the Anthropic API
The Fix#
export CLAUDE_CODE_ATTRIBUTION_HEADER=0
This removes the dynamic header from the system prompt, allowing the cache key to remain stable across requests.
How to Set It#
Option 1: settings.json (Recommended)#
{
"env": {
"CLAUDE_CODE_ATTRIBUTION_HEADER": "0"
}
}
Place in ~/.claude/settings.json (global) or .claude/settings.json (project-level).
Option 2: Shell Export#
export CLAUDE_CODE_ATTRIBUTION_HEADER=0
claude
Add to your .bashrc / .zshrc for persistence:
echo 'export CLAUDE_CODE_ATTRIBUTION_HEADER=0' >> ~/.bashrc
Option 3: Inline#
CLAUDE_CODE_ATTRIBUTION_HEADER=0 claude
Option 4: Dockerfile / CI#
ENV CLAUDE_CODE_ATTRIBUTION_HEADER=0
Option 5: With Proxy Setup#
ANTHROPIC_BASE_URL=https://my-proxy.com/v1 CLAUDE_CODE_ATTRIBUTION_HEADER=0 claude
Values: 0 = disabled (no billing header), any other value or unset = enabled (default).
Common Confusion: Env Var vs Git Attribution Settings#
This is the #1 source of confusion. There are two completely different attribution concepts in Claude Code:
CLAUDE_CODE_ATTRIBUTION_HEADER (Environment Variable)#
- Controls the
x-anthropic-billing-headerin API requests - Affects billing analytics and prompt caching
- Set via
envblock or shell export - Values:
0to disable, anything else to enable
attribution (Git Settings)#
- Controls the
Generated with Claude Codeline in git commit messages - Affects only git commit attribution, not API behavior
- Set in
.claude/settings.jsonor~/.claude/settings.json:
{
"preferences": {
"attribution": false
}
}
These are independent. Disabling the billing header (CLAUDE_CODE_ATTRIBUTION_HEADER=0) does not affect git commit attribution, and vice versa.
| Setting | What It Controls | Where to Set | Default |
|---|---|---|---|
CLAUDE_CODE_ATTRIBUTION_HEADER | API billing header in system prompt | env block or shell | Enabled |
attribution | "Generated with Claude Code" in commits | preferences block | Enabled |
FAQ#
Q: What does CLAUDE_CODE_ATTRIBUTION_HEADER do?
A: It controls whether Claude Code injects an x-anthropic-billing-header into the system prompt of API requests. This header contains version and entrypoint metadata for Anthropic's internal analytics. Setting it to 0 disables the header entirely.
Q: Why does Claude Code give a 400 error on AWS Bedrock?
A: Claude Code versions v2.1.29 through v2.1.37 injected the billing header directly into the system prompt. AWS Bedrock treats x-anthropic-billing-header as a reserved keyword and rejects it with a 400 error. The fix is either upgrading to v2.1.39+ or setting CLAUDE_CODE_ATTRIBUTION_HEADER=0.
Q: Does CLAUDE_CODE_ATTRIBUTION_HEADER affect git commit messages?
A: No. The env var controls only the API billing header. Git commit attribution ("Generated with Claude Code") is controlled separately by the attribution setting in your preferences. These are completely independent.
Q: Should I disable CLAUDE_CODE_ATTRIBUTION_HEADER when using a proxy?
A: Yes, if you care about prompt caching. The billing header changes on every request, which breaks prompt cache key matching. Set CLAUDE_CODE_ATTRIBUTION_HEADER=0 when using claude-code-router, liteLLM, or any custom API proxy.
Q: Is it safe to disable CLAUDE_CODE_ATTRIBUTION_HEADER?
A: Yes. Disabling it only removes the billing analytics header from API requests. It does not affect Claude Code functionality, model behavior, or response quality. Anthropic uses it for internal tracking — your usage still counts normally.
Q: What is the x-anthropic-billing-header?
A: It's a metadata string that Claude Code adds to the system prompt, formatted as x-anthropic-billing-header: cc_version=X.Y.Z; cc_entrypoint=cli; cch=HASH;. It helps Anthropic track which Claude Code version and interface generated each request. It's not a standard HTTP header — it's injected as text in the system prompt content array.
Related: 500+ Environment Variables Reference | CLAUDE_AUTOCOMPACT_PCT_OVERRIDE Guide | Context Window Management Guide | Claude Code Productivity Tips