{"record":{"id":"2a98e2b0d34e4930","repo":"JuliusBrussee/caveman","slug":"bedrock-requested-region-q-does-not-match-endpoin","errorCode":null,"errorMessage":"bedrock requested region %q does not match endpoint region %q","messagePattern":"bedrock requested region %q does not match endpoint region %q","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/providers/bedrock/routing.go","lineNumber":348,"sourceCode":"\t}\n\tidx := strings.LastIndex(rest, \"/\")\n\tif idx <= 0 || idx == len(rest)-1 {\n\t\treturn \"\", \"\"\n\t}\n\treturn rest[:idx], rest[idx+1:]\n}\n\n// resolveRegion keeps routing, allowlisting, and signing on one region. A\n// recognized endpoint host is authoritative; a contradictory client header is\n// rejected rather than validating one region and dialing another.\nfunc resolveRegion(req *http.Request, base *url.URL) (string, error) {\n\trequested := strings.TrimSpace(req.Header.Get(\"x-cave-aws-region\"))\n\thostRegion := \"\"\n\tif base != nil {\n\t\thostRegion = regionFromHost(base.Hostname())\n\t}\n\tif requested != \"\" && hostRegion != \"\" && requested != hostRegion {\n\t\treturn \"\", fmt.Errorf(\"bedrock requested region %q does not match endpoint region %q\", requested, hostRegion)\n\t}\n\tif hostRegion != \"\" {\n\t\treturn hostRegion, nil\n\t}\n\tif requested != \"\" {\n\t\treturn requested, nil\n\t}\n\tif r := regionFromHost(req.Header.Get(\"x-cave-bedrock-host\")); r != \"\" {\n\t\treturn r, nil\n\t}\n\treturn environmentRegion(), nil\n}\n\n// environmentRegion mirrors the precedence the proxy's own config uses\n// (CAVE_BEDROCK_REGION, then the standard AWS variables) so a request whose\n// upstream host does not name a region — a VPC endpoint, a PrivateLink host —\n// is signed for the region the operator actually configured instead of\n// silently falling back to us-east-1 and failing the signature.","sourceCodeStart":330,"sourceCodeEnd":366,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/providers/bedrock/routing.go#L330-L366","documentation":"resolveRegion keeps routing and AWS SigV4 signing on a single region: if the client explicitly requests a region via the x-cave-aws-region header while the configured base URL host already encodes a region (e.g. bedrock-runtime.eu-west-1.amazonaws.com), the two must agree. A contradictory pair is rejected rather than validating one region and dialing another, which would produce a signature scoped for the wrong region.","triggerScenarios":"Sending x-cave-aws-region: us-east-1 while the route's base URL host resolves to a different region (e.g. bedrock-runtime.eu-west-1.amazonaws.com, or a Mantle host bedrock-mantle.eu-west-1.api.aws) — in either direction of mismatch.","commonSituations":"Stale x-cave-aws-region header left from a previous configuration while the operator changed the base URL region; a multi-region deployment where clients pin regions that no longer match updated base URLs; copy-pasted route configs where the host was updated but client headers were not (or vice versa).","solutions":["Make x-cave-aws-region match the region in the configured base URL host, or remove the header and let the host region win","Update the route base_url to the region the clients request (e.g. bedrock-runtime.us-east-1.amazonaws.com)","Audit both sides after a region migration — header and host must change together","If no explicit region is needed, drop the header entirely; precedence is host region, then header, then CAVE_BEDROCK_REGION/AWS_REGION/AWS_DEFAULT_REGION"],"exampleFix":"// before\nbase_url: https://bedrock-runtime.eu-west-1.amazonaws.com\nx-cave-aws-region: us-east-1  // mismatch -> rejected\n// after\nx-cave-aws-region: eu-west-1","handlingStrategy":"validation","validationCode":"hostRegion := extractRegion(baseHost) // 2nd DNS label of bedrock-runtime.<region>.amazonaws.com\nif hdr := req.Header.Get(\"x-cave-aws-region\"); hdr != \"\" && hostRegion != \"\" && hdr != hostRegion {\n\t// fix header or base URL before sending\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Set x-cave-aws-region from the same config value that generates the base URL","Remove the header when the base URL already pins the region","After a region migration, update base_url and client headers in the same change","Add a config-lint check that diffs pinned regions across route config and client templates"],"tags":["bedrock","region","sigv4","header-conflict"],"backgroundTag":"conflicting-config-options","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"}