{"record":{"id":"621c30eac78ddcb7","repo":"JuliusBrussee/caveman","slug":"bedrock-request-signing-failed","errorCode":null,"errorMessage":"bedrock: request signing failed","messagePattern":"bedrock: request signing failed","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"proxy/providers/bedrock/signing.go","lineNumber":122,"sourceCode":"\ttoSign, err := http.NewRequestWithContext(ctx, req.Method, upstream.String(), nil)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"bedrock: could not build signing request: %w\", err)\n\t}\n\ttoSign.Header = out.Clone()\n\n\tsigningService := runtimeService\n\tif mantle {\n\t\tsigningService = mantleService\n\t}\n\tpayloadHash, err := requestPayloadHash(ctx, req)\n\tif err != nil {\n\t\treturn nil, err\n\t}\n\tsigner := awssig.Signer{Region: signingRegion(req, upstream), Service: signingService}\n\tif err := signer.Sign(toSign, creds, payloadHash, time.Now()); err != nil {\n\t\t// The error from Sign never contains the secret (see awssig docs); still,\n\t\t// return a generic mapping error rather than the raw text.\n\t\treturn nil, fmt.Errorf(\"bedrock: request signing failed\")\n\t}\n\n\tfor _, name := range []string{\"Authorization\", \"Host\", \"X-Amz-Date\", \"X-Amz-Content-Sha256\", \"X-Amz-Security-Token\"} {\n\t\tif v := toSign.Header.Get(name); v != \"\" {\n\t\t\tout.Set(name, v)\n\t\t}\n\t}\n\treturn out, nil\n}\n\n// matchesInboundSigningIdentity prevents a configured key or region from\n// silently replacing the principal/region selected by the SDK. This checks the\n// caller's scope claim, not the validity of its old signature: the standalone\n// loopback proxy is not an IAM authenticator. The signer below creates a new\n// signature covering the actual upstream authority, headers, and body.\nfunc matchesInboundSigningIdentity(req *http.Request, upstream *url.URL, creds awssig.Credentials) bool {\n\tif len(req.Header.Values(\"Authorization\")) != 1 {\n\t\treturn false","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/proxy/providers/bedrock/signing.go#L104-L140","documentation":"The awssig.Signer.Sign call failed while computing the SigV4 signature. The proxy deliberately returns a generic message instead of the raw signer error, because signing operates on secret material; the raw cause is only that Sign returned non-nil err.","triggerScenarios":"signer.Sign(toSign, creds, payloadHash, time.Now()) returns an error inside SanitizeAndMapHeaders — e.g. the credentials struct lacks an access key ID or secret, or the signer rejects the request form it was handed.","commonSituations":"AWS access keys parsed from x-cave-upstream-key are incomplete or contain characters the signer rejects; a session token of wrong form; signing invoked on a request whose required signed headers were stripped by earlier middleware.","solutions":["Verify the AWS credential value is the full accessKeyId:secretAccessKey[:sessionToken] form with no missing parts","Confirm the region and service used by the signer (signingRegion / runtimeService vs mantleService) are correct for the target Bedrock endpoint","Add temporary debug logging of the signer error (never the credentials) to identify the exact Sign failure, then fix the credential or request inputs"],"exampleFix":"// before\nkey := \"AKIA...\" // secret only, no secretAccessKey\n// after\nkey := \"AKIA...:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY\"","handlingStrategy":"try-catch","validationCode":"if cred.AccessKeyID == \"\" || cred.SecretAccessKey == \"\" { return errors.New(\"incomplete AWS credentials for SigV4\") }","typeGuard":null,"tryCatchPattern":"if err := sanitizeAndMap(); err != nil {\n\tif strings.Contains(err.Error(), \"request signing failed\") {\n\t\tlog.Printf(\"SigV4 signing failed; check AWS keys/region (details not exposed for safety): %v\", cause)\n\t}\n}","preventionTips":["Validate credential completeness before calling signing code","Confirm region/service mapping for the Bedrock endpoint type (mantle vs runtime)","Keep a debug flag to surface the raw signer error internally without exposing secrets"],"tags":["bedrock","sigv4","aws","authentication"],"backgroundTag":"api-request-failed","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"}