JuliusBrussee/caveman · error
bedrock: malformed AWS credentials (want…
Error message
bedrock: malformed AWS credentials (want accessKeyId:secretAccessKey[:sessionToken])
What it means
The credential string is expected as accessKeyId:secretAccessKey[:sessionToken]. If splitting on ":" (max 3 parts) yields fewer than 2 parts, or the access key or secret part is empty, the value is malformed and rejected so no partial SigV4 credentials are ever used.
Solutions
- Set the value to the complete accessKeyId:secretAccessKey form (append :sessionToken if using temporary credentials)
- Verify no intermediate config step split or trimmed the colon-delimited value
- If you only have a Bedrock API key (not IAM keys), do not use it here — set it as a plain key so it is inferred as bedrock_api_key
Example fix
// before // x-cave-upstream-key: AKIAIOSFODNN7EXAMPLE // after // x-cave-upstream-key: AKIAIOSFODNN7EXAMPLE:wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
Defensive patterns
Strategy: validation
Validate before calling
func validAWSKeyForm(raw string) bool {
parts := strings.SplitN(raw, ":", 3)
return len(parts) >= 2 && parts[0] != "" && parts[1] != ""
}
if !validAWSKeyForm(raw) { return errors.New("x-cave-upstream-key must be accessKeyId:secretAccessKey[:sessionToken]") } Prevention
- Validate the colon form whenever AWS keys are stored or rotated
- Never store only the access key ID
- Add a smoke test that parses stored credentials at deploy time
When it happens
Trigger: parseAWSCredentials receives a non-empty string that is not colon-form: a lone access key ("AKIA..."), only a secret, ":secret" with empty key part, "key:" with empty secret part, or a key pasted with the colon omitted.
Common situations: Storing only the AWS access key ID in x-cave-upstream-key; copying the key pair but dropping the colon or pasting only one half; a session-token-only value; config tools stripping the colon or splitting the value across fields.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must be set…
- bedrock: missing AWS credentials in x-cave-upstream-key
- ErrSigV4Configuration
- must not contain a newline
- awscreds: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/5f7d97131c145bc4.
Report an issue: GitHub.
Appendix: source
Thrown at proxy/providers/bedrock/signing.go:230
if strings.HasPrefix(key, "AKIA") || strings.HasPrefix(key, "ASIA") {
return "aws_access_keys", nil
}
return "bedrock_api_key", nil
default:
return "", fmt.Errorf("bedrock: unsupported credential auth kind")
}
}
// parseAWSCredentials decodes the "accessKeyId:secretAccessKey[:sessionToken]"
// form carried in x-cave-upstream-key into awssig.Credentials. It fails closed:
// a missing access key or secret is an error, never an unsigned passthrough.
func parseAWSCredentials(raw string) (awssig.Credentials, error) {
if raw == "" {
return awssig.Credentials{}, fmt.Errorf("bedrock: missing AWS credentials in x-cave-upstream-key")
}
parts := strings.SplitN(raw, ":", 3)
if len(parts) < 2 || parts[0] == "" || parts[1] == "" {
return awssig.Credentials{}, fmt.Errorf("bedrock: malformed AWS credentials (want accessKeyId:secretAccessKey[:sessionToken])")
}
creds := awssig.Credentials{AccessKeyID: parts[0], SecretAccessKey: parts[1]}
if len(parts) == 3 {
creds.SessionToken = parts[2]
}
return creds, nil
}
// copyIfPresent copies a header from src to dst when present (case-insensitive).
func copyIfPresent(dst, src http.Header, name string) {
if values := src.Values(name); len(values) > 0 {
for _, v := range values {
dst.Add(name, v)
}
}
}
View on GitHub (pinned to 3ee70a1026)