{"record":{"id":"a1cf0296ba3cacb0","repo":"JuliusBrussee/caveman","slug":"errsigv4configuration","errorCode":"ErrSigV4Configuration","errorMessage":"AWS SigV4 requests require matching AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN (when used), and region in the proxy process; configure them or use a Bedrock bearer API key","messagePattern":"AWS SigV4 requests require matching AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN \\(when used\\), and region in the proxy process; configure them or use a Bedrock bearer API key","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/providers/bedrock/signing.go","lineNumber":20,"sourceCode":"\nimport (\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"io\"\n\t\"net/http\"\n\t\"net/url\"\n\t\"strings\"\n\t\"time\"\n\n\t\"github.com/JuliusBrussee/caveman/proxy/providers\"\n\t\"github.com/JuliusBrussee/caveman/shared/platform/awssig\"\n)\n\n// ErrSigV4Configuration is safe to show to the caller: it contains no credential\n// material. An inbound signature is not a reusable credential after the proxy\n// changes the request authority/path or body.\nvar ErrSigV4Configuration = errors.New(\"AWS SigV4 requests require matching AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN (when used), and region in the proxy process; configure them or use a Bedrock bearer API key\")\n\n// SanitizeAndMapHeaders builds the upstream header set for Bedrock Runtime or\n// Mantle. Bedrock API keys use a bearer on Runtime and x-api-key on Mantle. IAM\n// access keys are SigV4-signed with the endpoint's distinct service name.\n//\n// IAM credentials retain the legacy \"accessKeyId:secretAccessKey[:sessionToken]\"\n// encoding at the adapter boundary. The secret is consumed only to derive the\n// signature and never copied into a forwarded header, log, error, or telemetry.\nfunc (a Adapter) SanitizeAndMapHeaders(ctx context.Context, req *http.Request, credential providers.Credential, upstream *url.URL) (http.Header, error) {\n\tout := http.Header{}\n\tcopyIfPresent(out, req.Header, \"content-type\")\n\tcopyIfPresent(out, req.Header, \"content-encoding\")\n\tcopyIfPresent(out, req.Header, \"accept\")\n\tcopyIfPresent(out, req.Header, \"accept-encoding\")\n\tmantle := endpointKindForPath(req.URL.Path) == endpointMantle\n\tif mantle {\n\t\tcopyIfPresent(out, req.Header, \"anthropic-version\")\n\t\tcopyIfPresent(out, req.Header, \"anthropic-beta\")","sourceCodeStart":2,"sourceCodeEnd":38,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/providers/bedrock/signing.go#L2-L38","documentation":"Bedrock SigV4 signing requires a complete, consistent IAM credential set (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, optional AWS_SESSION_TOKEN) plus a region inside the proxy process. ErrSigV4Configuration is a deliberately safe sentinel: it carries no credential material and is mapped by the gateway to HTTP 400 with code 'cave_bedrock_sigv4_configuration'.","triggerScenarios":"A Bedrock request arrives carrying SigV4-signed headers (or the adapter opts into SigV4) while the proxy's awscreds chain finds no usable IAM credentials or region — e.g. only AWS_ACCESS_KEY_ID set, or a Bedrock bearer key absent and env vars missing.","commonSituations":"Running the proxy locally with only a Bedrock API key while the client sends SigV4 headers; deploying to an environment without instance role/IRSA; setting a session token in one place but not the other; forgetting AWS_REGION in the proxy env.","solutions":["Export AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY (and AWS_SESSION_TOKEN if applicable) plus AWS_REGION in the proxy process environment","Attach an IAM role to the compute environment (instance profile, ECS task role, IRSA) so the credential chain resolves","Use a Bedrock bearer API key instead of SigV4 for this provider path","Verify the client's SigV4 credentials match the proxy-side credentials — mismatched pairs are rejected"],"exampleFix":"// before\nexport AWS_ACCESS_KEY_ID=AKIA...\n// after (complete set)\nexport AWS_ACCESS_KEY_ID=AKIA...\nexport AWS_SECRET_ACCESS_KEY=...\nexport AWS_SESSION_TOKEN=...\nexport AWS_REGION=us-east-1\n","handlingStrategy":"validation","validationCode":"func hasSigV4Env() bool {\n\tid, sec := os.Getenv(\"AWS_ACCESS_KEY_ID\"), os.Getenv(\"AWS_SECRET_ACCESS_KEY\")\n\treturn id != \"\" && sec != \"\" && os.Getenv(\"AWS_REGION\") != \"\"\n}\n","typeGuard":null,"tryCatchPattern":"if err != nil {\n\tif errors.Is(err, bedrock.ErrSigV4Configuration) {\n\t\t// 400: surface setup guidance to the operator\n\t\thttpx.Error(w, r, http.StatusBadRequest, \"cave_bedrock_sigv4_configuration\", err.Error())\n\t\treturn\n\t}\n}\n","preventionTips":["Set the full IAM credential set plus AWS_REGION in the proxy env","Attach an IAM role to the compute environment","Prefer a Bedrock bearer API key when SigV4 env is not available"],"tags":["aws","sigv4","bedrock","credentials","config"],"backgroundTag":"missing-credentials","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"}