openclaw - 💡(How to fix) Fix [Bug]: Anthropic provider sends prefixed 'anthropic/<model>' in request body to api.anthropic.com — causes 404 not_found_error on all direct Anthropic models (parallel to closed #41249 Google fix)

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…

OpenClaw 2026.5.22 sends the full provider/model reference (e.g. anthropic/claude-sonnet-4-6) as the model field in the request body to https://api.anthropic.com/v1/messages. The Anthropic API expects only claude-sonnet-4-6 and returns 404 not_found_error with the message model: anthropic/claude-sonnet-4-6 (echoing back the literal prefixed string).

This affects every anthropic/* model configured against the direct Anthropic provider:

  • anthropic/claude-opus-4-7 → 404
  • anthropic/claude-opus-4-6 → 404
  • anthropic/claude-sonnet-4-6 → 404
  • anthropic/claude-haiku-4-5 → 404
  • anthropic/claude-haiku-4-5-20251001 → 404

Only the catalog layer strips the prefix correctly (the gateway log shows requestedModel: "claude-sonnet-4-6"); the dispatch layer to Anthropic does not, and sends the full anthropic/... form on the wire.

This is the same shape as the closed Google bug #41249 ("Google model provider prefix not stripped — causes 404 on all Google model API calls") and the older #20107 (similar Anthropic 404, but root-caused there as an OAT endpoint routing issue, not the model-field prefix). The fix for #41249 (strip provider prefix from the model field before dispatch) has not been applied to the Anthropic provider adapter.

This is distinct from #20107: that one was about /v1/responses vs /v1/messages endpoint selection under OAT auth. My repro uses a plain API key (x-api-key) and confirms the call hits /v1/messages correctly — only the model field is wrong.

Error Message

{"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"req_011CbSXnF4B8dLinaHYxN2C5"} Note that Anthropic's error message literally echoes back the prefixed string, confirming it received the prefix in the body. "errorPreview": "{"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"sha256:..."}"

→ {"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"..."}

Root Cause

The bug is invisible to most users because the fallback succeeds — the only signal is the OpenRouter bill and the gateway log entries that nobody scrolls through.

Fix Action

Fix / Workaround

Only the catalog layer strips the prefix correctly (the gateway log shows requestedModel: "claude-sonnet-4-6"); the dispatch layer to Anthropic does not, and sends the full anthropic/... form on the wire.

This is the same shape as the closed Google bug #41249 ("Google model provider prefix not stripped — causes 404 on all Google model API calls") and the older #20107 (similar Anthropic 404, but root-caused there as an OAT endpoint routing issue, not the model-field prefix). The fix for #41249 (strip provider prefix from the model field before dispatch) has not been applied to the Anthropic provider adapter.

So requestedModel is correct (claude-sonnet-4-6), but somewhere between the catalog resolution and the HTTP dispatch the anthropic/ prefix gets re-added to the body's model field.

Code Example

ANTHROPIC_API_KEY=sk-ant-api03-...

---

openclaw infer model run --model "anthropic/claude-sonnet-4-6" --prompt "pong"
   openclaw infer model run --model "anthropic/claude-opus-4-7" --prompt "pong"
   openclaw infer model run --model "anthropic/claude-haiku-4-5" --prompt "pong"

---

{"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"req_011CbSXnF4B8dLinaHYxN2C5"}

---

"event": "model_fallback_decision",
"requestedProvider": "anthropic",
"requestedModel": "claude-sonnet-4-6",
"candidateProvider": "anthropic",
"candidateModel": "claude-sonnet-4-6",
"errorPreview": "{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model: anthropic/claude-sonnet-4-6\"},\"request_id\":\"sha256:...\"}"

---

# What OpenClaw is sending → 404
curl -sS -X POST https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"anthropic/claude-sonnet-4-6","max_tokens":10,"messages":[{"role":"user","content":"pong"}]}'
# → {"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"..."}

# What OpenClaw SHOULD send → 200
curl -sS -X POST https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":10,"messages":[{"role":"user","content":"pong"}]}'
# → {"model":"claude-sonnet-4-6","id":"msg_01TipRXo1vWgWP81XseTnCa2","type":"message","role":"assistant","content":[{"type":"text","text":"**Pong!** 🏓"}],...}
RAW_BUFFERClick to expand / collapse

Summary

OpenClaw 2026.5.22 sends the full provider/model reference (e.g. anthropic/claude-sonnet-4-6) as the model field in the request body to https://api.anthropic.com/v1/messages. The Anthropic API expects only claude-sonnet-4-6 and returns 404 not_found_error with the message model: anthropic/claude-sonnet-4-6 (echoing back the literal prefixed string).

This affects every anthropic/* model configured against the direct Anthropic provider:

  • anthropic/claude-opus-4-7 → 404
  • anthropic/claude-opus-4-6 → 404
  • anthropic/claude-sonnet-4-6 → 404
  • anthropic/claude-haiku-4-5 → 404
  • anthropic/claude-haiku-4-5-20251001 → 404

Only the catalog layer strips the prefix correctly (the gateway log shows requestedModel: "claude-sonnet-4-6"); the dispatch layer to Anthropic does not, and sends the full anthropic/... form on the wire.

This is the same shape as the closed Google bug #41249 ("Google model provider prefix not stripped — causes 404 on all Google model API calls") and the older #20107 (similar Anthropic 404, but root-caused there as an OAT endpoint routing issue, not the model-field prefix). The fix for #41249 (strip provider prefix from the model field before dispatch) has not been applied to the Anthropic provider adapter.

This is distinct from #20107: that one was about /v1/responses vs /v1/messages endpoint selection under OAT auth. My repro uses a plain API key (x-api-key) and confirms the call hits /v1/messages correctly — only the model field is wrong.

Impact

Production-critical. With a fallback chain that lists OpenRouter Opus as the next candidate after direct-Anthropic Haiku failures, every silent 404 caused fallback escalation to Opus, producing a >$140/day cost spike in our deployment from cron jobs alone (~194 escalations in 24h, 9.2M tokens billed at Opus prices instead of Haiku).

The bug is invisible to most users because the fallback succeeds — the only signal is the OpenRouter bill and the gateway log entries that nobody scrolls through.

Environment

  • OpenClaw CLI: 2026.5.22 (a374c3a)
  • OS: macOS 26.5 (build 25F71), arm64
  • Node: v24.16.0
  • Install method: pnpm global, LaunchAgent gateway
  • Auth: plain Anthropic API key (sk-ant-api03-..., 108 chars) via ANTHROPIC_API_KEY env var loaded from ~/.openclaw/.env
  • No custom models.providers.anthropic override — defaults from OpenClaw catalog

Steps to reproduce

  1. Configure an Anthropic API key in ~/.openclaw/.env:

    ANTHROPIC_API_KEY=sk-ant-api03-...
  2. Run any of these from the CLI:

    openclaw infer model run --model "anthropic/claude-sonnet-4-6" --prompt "pong"
    openclaw infer model run --model "anthropic/claude-opus-4-7" --prompt "pong"
    openclaw infer model run --model "anthropic/claude-haiku-4-5" --prompt "pong"

Expected

OpenClaw splits anthropic/claude-sonnet-4-6 into provider=anthropic and model=claude-sonnet-4-6, then sends only claude-sonnet-4-6 as the value of the model JSON field to https://api.anthropic.com/v1/messages.

The model ID strings claude-opus-4-7, claude-sonnet-4-6, claude-haiku-4-5-20251001, and claude-opus-4-6 are all live on Anthropic right now (verified via GET https://api.anthropic.com/v1/models against this key).

Actual

OpenClaw sends "model":"anthropic/claude-sonnet-4-6" in the request body. Anthropic responds:

{"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"req_011CbSXnF4B8dLinaHYxN2C5"}

Note that Anthropic's error message literally echoes back the prefixed string, confirming it received the prefix in the body.

The gateway log (/tmp/openclaw/openclaw-2026-05-27.log) shows the catalog layer parsed the provider correctly:

"event": "model_fallback_decision",
"requestedProvider": "anthropic",
"requestedModel": "claude-sonnet-4-6",
"candidateProvider": "anthropic",
"candidateModel": "claude-sonnet-4-6",
"errorPreview": "{\"type\":\"error\",\"error\":{\"type\":\"not_found_error\",\"message\":\"model: anthropic/claude-sonnet-4-6\"},\"request_id\":\"sha256:...\"}"

So requestedModel is correct (claude-sonnet-4-6), but somewhere between the catalog resolution and the HTTP dispatch the anthropic/ prefix gets re-added to the body's model field.

Control test: confirms the bug is in OpenClaw, not in Anthropic

Identical key, identical headers, identical endpoint. Only difference is the model field value:

# What OpenClaw is sending → 404
curl -sS -X POST https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"anthropic/claude-sonnet-4-6","max_tokens":10,"messages":[{"role":"user","content":"pong"}]}'
# → {"type":"error","error":{"type":"not_found_error","message":"model: anthropic/claude-sonnet-4-6"},"request_id":"..."}

# What OpenClaw SHOULD send → 200
curl -sS -X POST https://api.anthropic.com/v1/messages \
  -H "x-api-key: $ANTHROPIC_API_KEY" \
  -H "anthropic-version: 2023-06-01" \
  -H "content-type: application/json" \
  -d '{"model":"claude-sonnet-4-6","max_tokens":10,"messages":[{"role":"user","content":"pong"}]}'
# → {"model":"claude-sonnet-4-6","id":"msg_01TipRXo1vWgWP81XseTnCa2","type":"message","role":"assistant","content":[{"type":"text","text":"**Pong!** 🏓"}],...}

Both ran 2026-05-27 against the same ~/.openclaw/.env ANTHROPIC_API_KEY. Anthropic itself is healthy and serves all current-generation models without the prefix.

Sample request IDs

From failing OpenClaw calls (last 24h):

  • req_011CbSXnF4B8dLinaHYxN2C5
  • req_011CbSUjHeGGS3aYBGpdkzQd
  • req_011CbSUk3WjpxmcahJNjZWQx
  • req_011CbSUmQ14ie9iFfDg8V8Qg

Aggregate count from one 24h gateway log: 2,789 not_found_error events for anthropic/claude-haiku-4-5 alone.

Related issues

  • #41249 (CLOSED, regression fix for Google provider prefix-stripping) — same root pattern, applied to the Google adapter, never propagated to the Anthropic adapter.
  • #20107 (CLOSED, Anthropic OAT 404 → /v1/messages routing) — different mechanism (endpoint routing, not model-field prefix). My repro confirms /v1/messages is hit correctly; only the body's model field is wrong.
  • #15020 (CLOSED, "Anthropic Model ID Not Normalized in Isolated Sessions") — likely the same family. Closure may not have covered the direct provider path on 2026.5.22.

Suspected fix location

The PROVIDER_API_MAP-style normalization that models/google got in #41249 should be applied symmetrically to models/anthropic (and presumably to every */... provider that uses a single-segment model ID). The point of normalization is the request body builder, not the catalog resolver — the catalog already strips correctly.

Workaround (what we did)

Migrated 100% of cron jobs and main agent default to openrouter/anthropic/<model>. OpenRouter accepts the full prefix in its body without rejecting (it's its own routing scheme). Cost goes up modestly per token vs direct Anthropic, but stability is restored.

This workaround is unsatisfying: it pushes everyone off the direct path which Anthropic specifically markets, and through a proxy that adds its own failure modes (timeout chunks, occasional openrouter/auto brownouts, no prompt-cache benefits in some configurations).

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - 💡(How to fix) Fix [Bug]: Anthropic provider sends prefixed 'anthropic/<model>' in request body to api.anthropic.com — causes 404 not_found_error on all direct Anthropic models (parallel to closed #41249 Google fix)