Skip to content

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

@aws-zhehongb

Description

@aws-zhehongb

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingp1Showstopper bug preventing substantial subset of users from using the product, or incorrect docsprovider:bedrockAWS Bedrock API

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions