JuliusBrussee/caveman · error
ErrSigV4Configuration
ErrSigV4Configuration
Error message
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
What it means
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'.
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
Example fix
// before export AWS_ACCESS_KEY_ID=AKIA... // after (complete set) export AWS_ACCESS_KEY_ID=AKIA... export AWS_SECRET_ACCESS_KEY=... export AWS_SESSION_TOKEN=... export AWS_REGION=us-east-1
Defensive patterns
Strategy: validation
Validate before calling
func hasSigV4Env() bool {
id, sec := os.Getenv("AWS_ACCESS_KEY_ID"), os.Getenv("AWS_SECRET_ACCESS_KEY")
return id != "" && sec != "" && os.Getenv("AWS_REGION") != ""
}
Try / catch
if err != nil {
if errors.Is(err, bedrock.ErrSigV4Configuration) {
// 400: surface setup guidance to the operator
httpx.Error(w, r, http.StatusBadRequest, "cave_bedrock_sigv4_configuration", err.Error())
return
}
}
Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- bedrock: missing AWS credentials in x-cave-upstream-key
- AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be set…
- awssig: incomplete AWS credentials
- bedrock base url invalid
- bedrock configured endpoint kind
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/a1cf0296ba3cacb0.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/bedrock/signing.go:20
import (
"context"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"strings"
"time"
"github.com/JuliusBrussee/caveman/proxy/providers"
"github.com/JuliusBrussee/caveman/shared/platform/awssig"
)
// ErrSigV4Configuration is safe to show to the caller: it contains no credential
// material. An inbound signature is not a reusable credential after the proxy
// changes the request authority/path or body.
var 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")
// SanitizeAndMapHeaders builds the upstream header set for Bedrock Runtime or
// Mantle. Bedrock API keys use a bearer on Runtime and x-api-key on Mantle. IAM
// access keys are SigV4-signed with the endpoint's distinct service name.
//
// IAM credentials retain the legacy "accessKeyId:secretAccessKey[:sessionToken]"
// encoding at the adapter boundary. The secret is consumed only to derive the
// signature and never copied into a forwarded header, log, error, or telemetry.
func (a Adapter) SanitizeAndMapHeaders(ctx context.Context, req *http.Request, credential providers.Credential, upstream *url.URL) (http.Header, error) {
out := http.Header{}
copyIfPresent(out, req.Header, "content-type")
copyIfPresent(out, req.Header, "content-encoding")
copyIfPresent(out, req.Header, "accept")
copyIfPresent(out, req.Header, "accept-encoding")
mantle := endpointKindForPath(req.URL.Path) == endpointMantle
if mantle {
copyIfPresent(out, req.Header, "anthropic-version")
copyIfPresent(out, req.Header, "anthropic-beta")View on GitHub (pinned to 3ee70a1026)