anthropics / anthropics/claude-code-action
Bedrock: 400 error - x-anthropic-billing-header injected into system prompt rejected as reserved keyword
- Vorherrschende Sprache
- TypeScript
- Sterne
- 8.9k
- Forks
- 2.1k
- Ø Merge
- 3 T. 9 Std.
- Gemergte PRs (30 T.)
- 10
Beschreibung
# 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):
```js
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:
```js
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
```json
{
"type": "assistant",
"message": {
"model": "",
"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"
}
```
```json
{
"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
```yaml
- 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-2
```
## Suggested Fix
When using the Bedrock API path, the x-anthropic-billing-header attribution should either:
1. Be sent as an actual HTTP header instead of in the system prompt body, or
2. Be stripped/omitted from the system prompt for Bedrock requests, or
3. Be renamed to avoid Bedrock reserved keyword validation
## Failed Run
not available, private repo
## Related
- #914 -- Similar symptoms (exit code 1, 0 tokens) but different root cause (billing credits)
Beitragsleitfaden
Bewertung
Dieses Issue wurde noch nicht bewertet.