JuliusBrussee/caveman · error
bedrock model is not on the allowlist
Error message
bedrock model %q is not on the allowlist
What it means
ResolveUpstreamURL in the Bedrock adapter validates the model id from a /bedrock/model/{modelId}/{action} request path against the allowlist (built-in prefixes like anthropic.claude-, amazon.nova-, or the CAVE_BEDROCK_MODEL_ALLOWLIST override). The proxy deliberately blocks any model outside this closed list so unverified model ids (and their pricing/availability) cannot be routed to Bedrock. If the model id fails both the identifier validity check and prefix/allowlist matching, the request is rejected before any upstream call.
Solutions
- Verify the exact model id in the request path and fix typos (ids are prefix-matched, so 'anthropic.claude-3-5-sonnet-20241022-v2:0' matches 'anthropic.claude-')
- Add the model to CAVE_BEDROCK_MODEL_ALLOWLIST (comma-separated, prefix matches allowed) and restart the proxy
- If using an inference profile, keep the scope prefix (us./eu./global.) — it is stripped before prefix matching
- If the model is new on AWS, upgrade the proxy to a version whose defaultModelPrefixes covers it
- If passing a full model ARN, ensure it is well-formed (arn:aws:bedrock:<region>:<account>:foundation-model/...) — a malformed ARN falls back to identifier/prefix checks
Example fix
// before CAVE_BEDROCK_MODEL_ALLOWLIST=anthropic.claude-3-5-sonnet // request: /bedrock/model/anthropic.claude-opus-4/invoke -> rejected // after CAVE_BEDROCK_MODEL_ALLOWLIST=anthropic.claude-3-5-sonnet,anthropic.claude-
Defensive patterns
Strategy: validation
Validate before calling
func runtimeModelAllowed(modelID string) bool {
for _, p := range []string{"anthropic.claude-", "amazon.nova-", "amazon.titan-", "meta.llama2", "meta.llama3", "meta.llama4", "mistral.", "cohere.", "ai21."} {
if strings.HasPrefix(modelID, p) {
return true
}
}
return false
}
// call before issuing: if !runtimeModelAllowed(modelID) { fix config } Prevention
- Keep a single source of truth for model ids shared between client config and the proxy allowlist
- Prefix-check model ids against anthropic.claude-/amazon.nova- etc. before deploying client configs
- When narrowing CAVE_BEDROCK_MODEL_ALLOWLIST, diff it against all models your clients actually invoke
- Use full valid model ARNs if you need models outside the prefix list (they bypass prefixes when no custom allowlist is set)
When it happens
Trigger: A POST to /bedrock/model/<modelId>/invoke (or converse, count-tokens, etc.) where modelId does not match a default prefix and is not in CAVE_BEDROCK_MODEL_ALLOWLIST; e.g. a typo'd model id ('anthropic.claude35-sonnet'), a model from another vendor prefix not covered (e.g. 'deepseek.r1'), or an operator-set custom allowlist that omits the model.
Common situations: Typo in the model id in client config; using a newly released AWS model before the proxy's built-in prefix list was updated; an operator narrowing CAVE_BEDROCK_MODEL_ALLOWLIST and forgetting to include a model clients still use; expecting ARN-models to pass but supplying a malformed ARN (valid ARNs bypass the prefix list only when the allowlist env is unset).
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- bedrock region is not on the allowlist
- azure api-version is not on the allowlist
- bedrock action is not allowed
- bedrock base url invalid
- bedrock configured endpoint kind
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/679e1347e3b253a4.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/bedrock/routing.go:178
kind := endpointKindForPath(req.URL.Path)
if configuredKind := strings.ToLower(strings.TrimSpace(route.EndpointKind)); configuredKind != "" && configuredKind != kind {
return nil, fmt.Errorf("bedrock configured endpoint kind %q does not allow request kind %q", configuredKind, kind)
}
switch kind {
case endpointRuntime:
if !RegionAllowed(region) {
return nil, fmt.Errorf("bedrock region %q is not on the allowlist", region)
}
modelID, action := parseModelPath(req.URL.Path)
if modelID == "" || action == "" {
return nil, fmt.Errorf("bedrock request path %q does not name a model and action", req.URL.Path)
}
if !actionAllowed(action) {
return nil, fmt.Errorf("bedrock action %q is not allowed", action)
}
if !modelAllowed(modelID) {
return nil, fmt.Errorf("bedrock model %q is not on the allowlist", modelID)
}
base.Path = strings.TrimRight(base.Path, "/") + strings.TrimPrefix(req.URL.Path, "/bedrock")
case endpointMantle:
if !env.Bool("CAVE_BEDROCK_MANTLE_ENABLED", false) {
return nil, fmt.Errorf("bedrock Mantle endpoint is not enabled")
}
if !MantleRegionAllowed(region) {
return nil, fmt.Errorf("bedrock Mantle region %q is not on the allowlist", region)
}
if !mantleActionAllowed(req.URL.Path) {
return nil, fmt.Errorf("bedrock Mantle path %q is not allowed", req.URL.Path)
}
base, err = resolveMantleBase(base, region)
if err != nil {
return nil, err
}
base.Path = strings.TrimRight(base.Path, "/") + strings.TrimPrefix(req.URL.Path, "/bedrock")
default:View on GitHub (pinned to 3ee70a1026)