anthropics / anthropics/claude-code-action

Bedrock: 400 error - x-anthropic-billing-header injected into system prompt rejected as reserved keyword

Aperta
#928 0 commenti 3 reazioni 0 assegnatari Vedi su GitHub
bug p1 provider:bedrock
Lingua principale
TypeScript
Stelle
8.9k
Fork
2.1k
Merge medio
3g 9h
PR unite (30g)
10

Descrizione

# 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)

Guida per i contributori

Apri la guida per i contributori

Valutazione

Questa issue non è ancora stata valutata.

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.