-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Description
claude-code-action@v1 fails with Bedrock: x-anthropic-billing-header in system prompt rejected
Summary
claude-code-action@v1 with use_bedrock: true fails 100% of the time on Claude Code v2.1.38. The Bedrock API rejects the request because the CLI injects x-anthropic-billing-header directly into the system prompt, and Bedrock treats this as a reserved keyword.
Environment
- Action version: anthropics/claude-code-action@v1
- Claude Code version: 2.1.38
- Runner: ubuntu-latest
- Workflow trigger: pull_request
- Auth method: use_bedrock: true with IAM OIDC (aws-actions/configure-aws-credentials@v4)
- Model: global.anthropic.claude-sonnet-4-20250514-v1:0 (Bedrock cross-region)
Error
API Error: 400 x-anthropic-billing-header is a reserved keyword and may not be used in the system prompt.
Root Cause
Claude Code v2.1.38 constructs an attribution string and injects it as the first block of the system prompt:
x-anthropic-billing-header: cc_version=2.1.38.X; cc_entrypoint=claude-code-github-action; cch=00000;
This is built in cli.js (byte offset ~2702472 in the minified bundle):
z = `x-anthropic-billing-header: cc_version=${q}; cc_entrypoint=${K};${" cch=00000;"}`;The system prompt assembly code then places it as a text block with cacheScope: null:
if (G.startsWith("x-anthropic-billing-header")) _ = G;
// ...
if (_) j.push({text: _, cacheScope: null});The direct Anthropic API presumably handles or routes this attribution correctly. However, the Bedrock API validates system prompt content and rejects x-anthropic-billing-header as a reserved keyword, returning HTTP 400 before the model ever sees the request.
Evidence from Logs
{
"type": "assistant",
"message": {
"model": "<synthetic>",
"usage": {
"input_tokens": 0,
"output_tokens": 0
},
"content": [
{
"type": "text",
"text": "API Error: 400 x-anthropic-billing-header is a reserved keyword and may not be used in the system prompt."
}
]
},
"error": "unknown"
}{
"type": "result",
"is_error": true,
"duration_ms": 741,
"duration_api_ms": 0,
"num_turns": 1,
"total_cost_usd": 0,
"result": "API Error: 400 x-anthropic-billing-header is a reserved keyword and may not be used in the system prompt."
}Key indicators:
- input_tokens: 0, output_tokens: 0 -- request rejected before processing
- duration_ms: 741 -- instant validation failure
- model: synthetic -- error response is synthesized, not from the model
Reproduction
Any claude-code-action@v1 workflow with use_bedrock: true on Claude Code v2.1.38 will fail.
Workflow Configuration
- name: Code Review
uses: anthropics/claude-code-action@v1
continue-on-error: true
with:
show_full_output: true
use_bedrock: true
github_token: ${{ secrets.GITHUB_TOKEN }}
prompt: |
/review
[review prompt]
claude_args: |
--model global.anthropic.claude-sonnet-4-20250514-v1:0
--allowedTools "mcp__github_inline_comment__create_inline_comment,Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*)"
env:
AWS_REGION: us-west-2Suggested Fix
When using the Bedrock API path, the x-anthropic-billing-header attribution should either:
- Be sent as an actual HTTP header instead of in the system prompt body, or
- Be stripped/omitted from the system prompt for Bedrock requests, or
- Be renamed to avoid Bedrock reserved keyword validation
Failed Run
not available, private repo
Related
- claude-code-action@v1 100% failure rate for 3+ days - exits with code 1 before any API calls #914 -- Similar symptoms (exit code 1, 0 tokens) but different root cause (billing credits)