{"record":{"id":"d5f21e974713aa18","repo":"JuliusBrussee/caveman","slug":"bedrock-mantle-path-q-is-not-allowed","errorCode":null,"errorMessage":"bedrock Mantle path %q is not allowed","messagePattern":"bedrock Mantle path %q is not allowed","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/providers/bedrock/routing.go","lineNumber":189,"sourceCode":"\t\tif modelID == \"\" || action == \"\" {\n\t\t\treturn nil, fmt.Errorf(\"bedrock request path %q does not name a model and action\", req.URL.Path)\n\t\t}\n\t\tif !actionAllowed(action) {\n\t\t\treturn nil, fmt.Errorf(\"bedrock action %q is not allowed\", action)\n\t\t}\n\t\tif !modelAllowed(modelID) {\n\t\t\treturn nil, fmt.Errorf(\"bedrock model %q is not on the allowlist\", modelID)\n\t\t}\n\t\tbase.Path = strings.TrimRight(base.Path, \"/\") + strings.TrimPrefix(req.URL.Path, \"/bedrock\")\n\tcase endpointMantle:\n\t\tif !env.Bool(\"CAVE_BEDROCK_MANTLE_ENABLED\", false) {\n\t\t\treturn nil, fmt.Errorf(\"bedrock Mantle endpoint is not enabled\")\n\t\t}\n\t\tif !MantleRegionAllowed(region) {\n\t\t\treturn nil, fmt.Errorf(\"bedrock Mantle region %q is not on the allowlist\", region)\n\t\t}\n\t\tif !mantleActionAllowed(req.URL.Path) {\n\t\t\treturn nil, fmt.Errorf(\"bedrock Mantle path %q is not allowed\", req.URL.Path)\n\t\t}\n\t\tbase, err = resolveMantleBase(base, region)\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\tbase.Path = strings.TrimRight(base.Path, \"/\") + strings.TrimPrefix(req.URL.Path, \"/bedrock\")\n\tdefault:\n\t\treturn nil, fmt.Errorf(\"bedrock request path %q is not allowed\", req.URL.Path)\n\t}\n\tbase.RawQuery = req.URL.RawQuery\n\n\tif env.IsProduction() {\n\t\tif err := providers.ValidateUpstreamEndpoint(ctx, base, ssrf.ManagedConfig()); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\thostKind, _, ok := bedrockHostKind(base.Hostname())\n\t\tif !ok || hostKind != kind {\n\t\t\treturn nil, fmt.Errorf(\"bedrock endpoint host %q does not match endpoint kind %q\", base.Hostname(), kind)","sourceCodeStart":171,"sourceCodeEnd":207,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/providers/bedrock/routing.go#L171-L207","documentation":"The implemented Mantle lane serves exactly two paths: /bedrock/anthropic/v1/messages and /bedrock/anthropic/v1/messages/count_tokens. Any other path under /bedrock/anthropic/ (AWS's OpenAI-compatible Mantle surfaces are deliberately not routed yet) is rejected by mantleActionAllowed in ResolveUpstreamURL.","triggerScenarios":"A request like POST /bedrock/anthropic/v1/complete, /bedrock/anthropic/v1/chat/completions, /bedrock/anthropic/v1/models, or a mistyped messages path (e.g. /bedrock/anthropic/v1/message) while endpointKindForPath classifies it as Mantle (prefix /bedrock/anthropic/).","commonSituations":"Pointing an OpenAI SDK-style client at the Mantle prefix; using the legacy Anthropic /v1/complete endpoint; a trailing-slash or typo variant of /v1/messages; assuming all Anthropic API paths are proxied through Mantle.","solutions":["Use exactly POST /bedrock/anthropic/v1/messages (or .../v1/messages/count_tokens) — check for typos and trailing slashes","If you need the OpenAI-compatible surface or legacy completions, route via a different provider adapter; Mantle here is Anthropic-Messages-only","If targeting Bedrock Runtime model invocation, use /bedrock/model/<modelId>/invoke|converse instead","Upgrade the proxy if a newer Mantle path was recently added to AWS and you need support for it"],"exampleFix":"// before\nPOST /bedrock/anthropic/v1/message  // typo -> rejected\n// after\nPOST /bedrock/anthropic/v1/messages","handlingStrategy":"validation","validationCode":"allowedMantle := map[string]bool{\"/bedrock/anthropic/v1/messages\": true, \"/bedrock/anthropic/v1/messages/count_tokens\": true}\nif !allowedMantle[path] {\n\t// correct the path before sending\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Hard-code the two exact Mantle paths in client SDK wrappers","Avoid OpenAI-style path construction against the /bedrock/anthropic/ mount","Add an integration test asserting the exact URL used for Mantle calls"],"tags":["bedrock","mantle","routing","path-validation"],"backgroundTag":"invalid-url","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}