JuliusBrussee/caveman · critical
cache-replay: Bedrock bearer token or AWS access credentials
Error message
cache-replay: Bedrock bearer token or AWS access credentials unavailable
What it means
Returned by validateProviderCredentials for bedrock traces: neither AWS_BEARER_TOKEN_BEDROCK is set nor the classic AWS_ACCESS_KEY_ID + AWS_SECRET_ACCESS_KEY pair is complete (both must be non-empty). Bedrock accepts either a bearer token or long-lived access keys, and the check fails only when neither path is fully satisfied.
Source
Thrown at cacheengine/cmd/cache-replay/main.go:389
providers[record.Provider] = true
}
for provider := range providers {
switch provider {
case "openai":
if os.Getenv("OPENAI_API_KEY") == "" {
return errors.New("cache-replay: OPENAI_API_KEY unavailable")
}
case "anthropic":
if os.Getenv("ANTHROPIC_API_KEY") == "" {
return errors.New("cache-replay: ANTHROPIC_API_KEY unavailable")
}
case "gemini":
if os.Getenv("GEMINI_API_KEY") == "" {
return errors.New("cache-replay: GEMINI_API_KEY unavailable")
}
case "bedrock":
if os.Getenv("AWS_BEARER_TOKEN_BEDROCK") == "" && (os.Getenv("AWS_ACCESS_KEY_ID") == "" || os.Getenv("AWS_SECRET_ACCESS_KEY") == "") {
return errors.New("cache-replay: Bedrock bearer token or AWS access credentials unavailable")
}
default:
return fmt.Errorf("cache-replay: unsupported provider %q", provider)
}
}
return nil
}
func verifierEnvironment(extra []string) ([]string, error) {
allowed := map[string]bool{"PATH": true, "LANG": true, "LC_ALL": true, "TMPDIR": true}
blocked := map[string]bool{
"OPENAI_API_KEY": true, "ANTHROPIC_API_KEY": true, "GEMINI_API_KEY": true,
"AWS_BEARER_TOKEN_BEDROCK": true, "AWS_ACCESS_KEY_ID": true, "AWS_SECRET_ACCESS_KEY": true, "AWS_SESSION_TOKEN": true,
}
for _, name := range extra {
name = strings.TrimSpace(name)
if !validEnvironmentName(name) || blocked[name] {
return nil, fmt.Errorf("cache-replay: verifier environment variable %q is invalid or credential-bearing", name)View on GitHub (pinned to 27d5a3981a)
Solutions
- Export AWS_BEARER_TOKEN_BEDROCK (preferred) OR both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
- If credentials live in an AWS profile/session, materialize them into the env for the cache-replay process (e.g. via aws configure export-credentials or your SSO tooling)
- Check for half-written pairs: one of the two classic vars missing still fails
Example fix
# before # only AWS_ACCESS_KEY_ID exported cache-replay -execute ... # after export AWS_ACCESS_KEY_ID=... AWS_SECRET_ACCESS_KEY=... # or: export AWS_BEARER_TOKEN_BEDROCK=... cache-replay -execute ...
Defensive patterns
Strategy: validation
Validate before calling
if providers["bedrock"] {
bearer := os.Getenv("AWS_BEARER_TOKEN_BEDROCK") != ""
classic := os.Getenv("AWS_ACCESS_KEY_ID") != "" && os.Getenv("AWS_SECRET_ACCESS_KEY") != ""
if !bearer && !classic {
return errors.New("provide AWS_BEARER_TOKEN_BEDROCK or both AWS access env vars")
}
} Prevention
- Materialize AWS SSO/profile credentials into env vars for the replay process — the tool reads env only
- Ensure both halves of the classic pair are exported; a lone access key ID still fails
When it happens
Trigger: Trace with provider "bedrock" records where AWS_BEARER_TOKEN_BEDROCK is unset AND at least one of AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY is empty. Setting only the access key ID without the secret also triggers it.
Common situations: Relying on an AWS profile file or SSO session instead of env vars (the tool only inspects env); bearer token named differently; key rotation script updated one of the two env vars; CI masking one variable due to a name collision.
Related errors
- cache-replay: OPENAI_API_KEY unavailable
- cache-replay: ANTHROPIC_API_KEY unavailable
- cache-replay: GEMINI_API_KEY unavailable
- no provider credential detected; pass --provider
- multiple provider credentials detected; pass --provider
AI-assisted analysis of JuliusBrussee/caveman@27d5a3981a (2026-08-15).
Data as JSON: /api/errors/3a6ff241b46eb026.
Report an issue: GitHub.