Skip to content

api-proxy: Anthropic API calls rejected despite correct routing (auth chain failure) #1527

@lpcox

Description

@lpcox

Problem

After the chroot key helper fix (PR #1508), the script copy and config path updates work correctly, and the firewall allows traffic through to api.anthropic.com. However, all Anthropic API calls fail with error: "unknown", error_status: null, and zero tokens consumed — indicating the requests reach Anthropic but are rejected.

Observed behavior (from gh-aw#23614 comment)

[entrypoint] ✓ Updated apiKeyHelper path in /host/home/runner/.claude.json
[entrypoint] ✓ Updated apiKeyHelper path in /host/home/runner/.claude/settings.json
[entrypoint] Claude key helper copied to chroot at /tmp/awf-lib/get-claude-key.sh
  • ✅ Chroot fix works (paths updated)
  • ✅ Squid allows 4 requests to api.anthropic.com (0 blocked)
  • ❌ All 10 API retries fail: error: "unknown", error_status: null
  • ❌ Zero tokens consumed, zero cost — API never successfully authenticated

The ANTHROPIC_API_KEY works fine outside gh-aw (validated by the activation step).

Environment

Authentication Chain Analysis

The expected chain:

Claude Code → apiKeyHelper (get-claude-key.sh)
  → returns "sk-ant-placeholder-key-for-credential-isolation"
  → sends x-api-key: <placeholder> to ANTHROPIC_BASE_URL (http://172.30.0.30:10001)
  → api-proxy strips x-api-key, injects real ANTHROPIC_API_KEY
  → forwards through Squid to api.anthropic.com
  → Anthropic authenticates with real key

The chain breaks somewhere between the api-proxy injecting the key and Anthropic accepting the request.

Hypotheses

H1: Claude Code 2.1.88 auth mechanism mismatch

Claude Code may use a different auth flow than the standard Anthropic SDK:

  • Might send Authorization: Bearer instead of or in addition to x-api-key
  • Might use a different API endpoint path (e.g., /v1/complete vs /v1/messages)
  • Might require an anthropic-version header value newer than the proxy's default 2023-06-01

The api-proxy strips authorization and x-api-key headers and only injects x-api-key. If Claude Code requires a header the proxy doesn't inject, auth would fail.

H2: ANTHROPIC_AUTH_TOKEN interference

The agent has TWO different placeholder values:

  • ANTHROPIC_AUTH_TOKEN=placeholder-token-for-credential-isolation (env var, docker-manager.ts:1450)
  • apiKeyHelper returns sk-ant-placeholder-key-for-credential-isolation (script output)

Claude Code might prefer ANTHROPIC_AUTH_TOKEN over apiKeyHelper for certain operations, sending it as a different header that the proxy doesn't handle. Or the two conflicting values might cause confusion in Claude Code's auth logic.

H3: SSE streaming response not proxied correctly

The error_status: null (not 401/403) suggests Claude Code can't parse the response rather than receiving a clear auth error. The api-proxy uses proxyRequest() which pipes the upstream response back — if SSE chunked encoding is mangled, Claude Code would see "unknown" errors.

H4: Squid CONNECT tunnel issue

The 4 "allowed" Squid requests might be CONNECT tunnel establishments (HTTP 200), not the actual API calls. The real API responses within the tunnel might be failing. Squid logs showing TCP_TUNNEL:HIER_DIRECT with status 200 only means the tunnel was established, not that the API call succeeded.

Suggested Investigation

  1. Enable api-proxy debug logging and check if requests are being received and forwarded with the correct x-api-key header
  2. Compare headers sent by Claude Code 2.1.88 vs what the proxy expects — check if Claude Code sends auth in a header the proxy doesn't handle
  3. Check the Anthropic response status in the api-proxy logs (before it's sent back to the agent)
  4. Test with curl through the same proxy chain to isolate whether it's a Claude Code-specific issue:
    curl -v http://172.30.0.30:10001/v1/messages \
      -H "content-type: application/json" \
      -H "anthropic-version: 2023-06-01" \
      -d '{"model":"claude-sonnet-4-20250514","max_tokens":10,"messages":[{"role":"user","content":"hi"}]}'
  5. Try removing ANTHROPIC_AUTH_TOKEN from the agent environment to see if it interferes with apiKeyHelper

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions