AWS Bedrock LiteLLM GenAI proxy

LiteLLM to Bedrock: 'unsupported model id schema' / OAIBackend error

Fix the LiteLLM 'unsupported model id schema' / OAIBackend error when proxying to AWS Bedrock: the model string lacks a recognised provider prefix or the wrong route is used for inference-profile and application-inference-profile ARNs.

Jerzy Kopaczewski ·
You are calling AWS Bedrock through a LiteLLM proxy (or the LiteLLM SDK) and the request fails before it ever reaches AWS, with an error mentioning an unsupported model id schema on an OAIBackend route. The model works when you call Bedrock directly with boto3, which makes this look like an AWS problem. It is not: it is a LiteLLM model-routing / config problem. This runbook shows why and how to fix it.

This runbook covers LiteLLM-to-Bedrock model-ID routing errors. For the architecture behind running models on AWS, see LLM Inference on AWS - Bedrock vs SageMaker vs Self-Hosted on EKS, and for the managed agent layer, Amazon Bedrock AgentCore pricing and architecture. If you are standing up a model gateway and want it done right, book a consultation.

Symptom

A request through LiteLLM to a Bedrock model fails immediately. The error references the model ID and a backend/provider it could not resolve:

# Typical LiteLLM proxy / SDK error (wording varies by version):
# litellm.BadRequestError: ... unsupported model id schema ...
# or: LLM Provider NOT provided. Pass in the LLM provider you are trying to call.
# or: Invalid model name passed in model=<your-model> ... OAIBackend
# or: GetLLMProvider Exception - model=<your-model>, custom_llm_provider=...

# The tell: the model string you passed has NO recognised provider prefix,
# so LiteLLM fell through to its OpenAI-compatible backend (OAIBackend) and
# could not match a Bedrock schema for it.

# Confirm the SAME model works with boto3 directly (proves AWS/creds are fine).
# Current Sonnet models are inference-profile only, so invoke by the profile ID:
aws bedrock-runtime invoke-model \
  --model-id eu.anthropic.claude-sonnet-5-5 \
  --body '{"anthropic_version":"bedrock-2023-05-31","max_tokens":16,"messages":[{"role":"user","content":"hi"}]}' \
  --cli-binary-format raw-in-base64-out /dev/stdout
# If this succeeds but LiteLLM fails, the problem is the LiteLLM model string, not AWS.

Isolating the layer is the whole game here:

Where it fails Meaning This runbook?
boto3 direct works, LiteLLM fails LiteLLM model string lacks the bedrock/ provider prefix / wrong route Yes
boto3 direct also fails with AccessDenied IAM / model access, not routing No (model-access runbook)
boto3 fails with ValidationException Wrong model ID or region No (fix the model ID)

Root Cause

LiteLLM decides how to call a model by parsing a provider prefix off the front of the model string. For AWS Bedrock that prefix is bedrock/ (with sub-routes like bedrock/converse/ and bedrock/invoke/). When the prefix is missing or wrong, LiteLLM cannot classify the model as a Bedrock call, falls through to its OpenAI-compatible backend (OAIBackend), and then fails because the raw Bedrock model ID is not a valid schema for that backend. The error is raised before any network call to AWS, which is why your credentials and the direct boto3 call are irrelevant to it.

The specific triggers:

1. No provider prefix on the model string (the usual cause).

You passed eu.anthropic.claude-sonnet-5-5 where LiteLLM expected a prefixed form such as bedrock/converse/eu.anthropic.claude-sonnet-5-5. Without bedrock/, LiteLLM has no way to know this is a Bedrock model and treats it as an OpenAI-style name.

2. A raw inference-profile or application-inference-profile ID without the right route.

Cross-region inference profiles (the eu., us., and global. prefixed IDs, e.g. eu.anthropic.claude-sonnet-5-5) and application-inference-profile ARNs do not carry a provider that LiteLLM can infer. Passed bare, they trip the same fall-through. They need an explicit route, bedrock/converse/, so LiteLLM knows which Bedrock API to call. This matters more now than it used to: current Sonnet models are inference-profile only (there is no bare on-demand base-ID to call), so in practice the Bedrock model you pass to LiteLLM today is almost always a profile ID that needs this route.

3. A proxy model_list entry with model_name set but no concrete litellm_params.model.

In the proxy YAML, model_name is only the public alias clients call. The actual Bedrock model has to be set in litellm_params.model, prefixed with bedrock/. If that is missing or unprefixed, every call to that alias fails to route.

4. A typo or custom alias that is not a real Bedrock model ID.

A hand-written alias (my-claude, a provisioned-throughput nickname) that was never mapped to a concrete bedrock/... model ID has no schema to resolve to.

Solution

A) Add the bedrock/ provider prefix (fixes most cases).

# LiteLLM SDK
import litellm

# WRONG - no provider prefix, falls through to OAIBackend:
# litellm.completion(model="eu.anthropic.claude-sonnet-5-5", messages=...)

# RIGHT - bedrock/converse/ route + the inference-profile ID:
response = litellm.completion(
    model="bedrock/converse/eu.anthropic.claude-sonnet-5-5",
    messages=[{"role": "user", "content": "hi"}],
    aws_region_name="eu-west-1",
)

B) Fix the proxy model_list - prefix the real model, keep a clean alias.

# config.yaml for the LiteLLM proxy
model_list:
  # Clients call "claude-sonnet"; LiteLLM routes it to the prefixed Bedrock model.
  - model_name: claude-sonnet
    litellm_params:
      model: bedrock/converse/eu.anthropic.claude-sonnet-5-5   # concrete + prefixed route
      aws_region_name: eu-west-1

  # WRONG pattern that causes the error - alias with no concrete prefixed model:
  # - model_name: claude-sonnet
  #   litellm_params:
  #     model: eu.anthropic.claude-sonnet-5-5   # missing bedrock/converse/ route
# Restart the proxy and confirm the model is registered under its alias:
curl -s http://localhost:4000/v1/models -H "Authorization: Bearer $LITELLM_KEY" \
  | python -c "import sys,json; print([m['id'] for m in json.load(sys.stdin)['data']])"
# Expected: your alias (e.g. "claude-sonnet") appears in the list.

C) Use an explicit route for inference-profile and application-inference-profile ARNs.

model_list:
  # Cross-region inference profile - needs the converse route so LiteLLM
  # knows which Bedrock API to target.
  - model_name: claude-sonnet-xr
    litellm_params:
      model: bedrock/converse/us.anthropic.claude-sonnet-5-5
      aws_region_name: us-east-1

  # Application inference profile by ARN - same idea, explicit route.
  - model_name: claude-app-profile
    litellm_params:
      model: bedrock/converse/arn:aws:bedrock:us-east-1:111122223333:application-inference-profile/abc123
      aws_region_name: us-east-1

D) Map custom aliases to a concrete Bedrock model ID.

model_list:
  # A provisioned-throughput or custom name must resolve to a real, prefixed model.
  - model_name: my-claude          # friendly name your app uses
    litellm_params:
      model: bedrock/converse/eu.anthropic.claude-sonnet-5-5  # the real thing
      aws_region_name: eu-west-1
# Never pass a nickname straight through - LiteLLM has no schema for "my-claude".

E) Pin the provider explicitly if you cannot change the model string.

# If the model string is fixed upstream and you cannot add the prefix,
# tell LiteLLM the provider directly:
response = litellm.completion(
    model="eu.anthropic.claude-sonnet-5-5",
    custom_llm_provider="bedrock",     # forces the Bedrock route
    messages=[{"role": "user", "content": "hi"}],
    aws_region_name="eu-west-1",
)

Validation

# 1. A prefixed call through LiteLLM now returns a completion, not a routing error.
python -c "
import litellm
r = litellm.completion(
    model='bedrock/converse/eu.anthropic.claude-sonnet-5-5',
    messages=[{'role':'user','content':'reply with OK'}],
    aws_region_name='eu-west-1',
)
print(r.choices[0].message.content)
"
# Expected: a normal completion. No 'unsupported model id schema' / OAIBackend error.

# 2. Through the proxy, call by the alias and confirm a 200.
curl -s -o /dev/null -w "%{http_code}\n" http://localhost:4000/v1/chat/completions \
  -H "Authorization: Bearer $LITELLM_KEY" \
  -H "Content-Type: application/json" \
  -d '{"model":"claude-sonnet","messages":[{"role":"user","content":"hi"}]}'
# Expected: 200.

# 3. Confirm LiteLLM resolved the provider as bedrock (debug once, then turn off).
python -c "
import litellm
litellm.set_verbose = True
litellm.completion(model='bedrock/converse/eu.anthropic.claude-sonnet-5-5',
    messages=[{'role':'user','content':'hi'}], aws_region_name='eu-west-1')
" 2>&1 | grep -i "provider" | head -3
# Expected: log lines showing custom_llm_provider = bedrock (not openai / OAIBackend).
This error is almost always a missing bedrock/ prefix on the model string, not an AWS problem - which is why the same model works from boto3. Rule of thumb: in LiteLLM, every Bedrock model ID is prefixed (bedrock/<model-id>), inference-profile and application-inference-profile ARNs take an explicit route (bedrock/converse/<id-or-arn>), and in the proxy YAML the real prefixed model always goes in litellm_params.model, never just in model_name.

 

Jerzy Kopaczewski

Building a model gateway on Bedrock?

Book a free 30-minute call. We help teams stand up LiteLLM or a Bedrock gateway with clean model routing, fallback, and cost controls, so routing errors like this never reach production.

Book a call