JuliusBrussee/caveman · error
awscreds: sts assume role with web identity: http
Error message
awscreds: sts assume role with web identity: http %d%s
What it means
fromWebIdentity requires HTTP 200 from STS. When AssumeRoleWithWebIdentity returns any other status, this error reports the status code plus stsErrorCode(body), which extracts the STS error code/type from the XML error payload (e.g. InvalidIdentityToken, ExpiredToken, AccessDenied).
Solutions
- Read the STS error code embedded in the message (InvalidIdentityToken, AccessDenied, ExpiredToken...) and address that specific cause
- Verify AWS_ROLE_ARN exists and its trust policy trusts the OIDC provider of the token; check the token's aud matches the provider's client ID
- Get a fresh token — restart the pod or re-mount the serviceaccount token if it expired
- Handle 429/5xx with retries and backoff; check STS regional endpoint correctness (sts.<region>.amazonaws.com vs global)
Example fix
// before
// AWS_ROLE_ARN=arn:aws:iam::123:role/wrong-role -> http 403 AccessDenied
// after
// ensure trust policy:
// "Principal": {"Federated": "arn:aws:iam::123:oidc-provider/oidc.eks.us-east-1.amazonaws.com"},
// condition on sub = system:serviceaccount:<ns>:<sa>
os.Setenv("AWS_ROLE_ARN", "arn:aws:iam::123:role/pod-role") Defensive patterns
Strategy: try-catch
Validate before calling
// validate role ARN shape and token freshness before the exchange
if !strings.HasPrefix(os.Getenv("AWS_ROLE_ARN"), "arn:aws:iam::") { return errors.New("bad AWS_ROLE_ARN") }
tok, _ := os.ReadFile(os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE"))
parts := strings.Split(string(tok), ".")
if len(parts) != 3 { return errors.New("malformed identity token") } Try / catch
creds, err := awscreds.Credentials(ctx, p)
if err != nil && strings.Contains(err.Error(), "sts assume role with web identity: http ") {
switch {
case strings.Contains(err.Error(), "InvalidIdentityToken"), strings.Contains(err.Error(), "ExpiredToken"):
// refresh token / restart pod
case strings.Contains(err.Error(), "AccessDenied"):
// fix role trust policy / ARN
default:
// 429/5xx: retry with backoff
}
} Prevention
- Verify the OIDC provider, thumbprint, and audience (aud) match the serviceaccount token
- Ensure AWS_ROLE_ARN's trust policy federates the correct OIDC provider and sub condition
- Handle 429/5xx with exponential backoff in callers
- Use the regional STS endpoint consistent with your cluster setup
When it happens
Trigger: p.sts.Do succeeds but resp.StatusCode != 200: the web identity token is expired or invalid, the role ARN is wrong/not trusted by the OIDC provider, the audience (aud) doesn't match, or the request is malformed (400) / throttled (429/503).
Common situations: EKS pods whose serviceaccount token expired or whose OIDC provider thumbprint/audience is misconfigured; AWS_ROLE_ARN pointing to a role the token's issuer isn't trusted to assume; regional STS endpoint mismatch; throttling under high pod churn.
Related errors
- awscreds: build sts request
- awscreds: sts assume role with web identity failed
- awscreds: read sts response
- awscreds: : http
- awscreds: returned incomplete credentials
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/efc9c44a10668fbb.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/awscreds/awscreds.go:347
}
req, err := http.NewRequestWithContext(ctx, http.MethodPost, p.stsEndpoint, strings.NewReader(form.Encode()))
if err != nil {
return nil, fmt.Errorf("awscreds: build sts request: %w", err)
}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/xml")
resp, err := p.sts.Do(req)
if err != nil {
// A transport error can carry the request URL but never the form body.
return nil, fmt.Errorf("awscreds: sts assume role with web identity failed: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))
if err != nil {
return nil, fmt.Errorf("awscreds: read sts response: %w", err)
}
if resp.StatusCode != http.StatusOK {
return nil, fmt.Errorf("awscreds: sts assume role with web identity: http %d%s", resp.StatusCode, stsErrorCode(body))
}
var parsed struct {
XMLName xml.Name `xml:"AssumeRoleWithWebIdentityResponse"`
Result struct {
Credentials struct {
AccessKeyID string `xml:"AccessKeyId"`
SecretAccessKey string `xml:"SecretAccessKey"`
SessionToken string `xml:"SessionToken"`
Expiration string `xml:"Expiration"`
} `xml:"Credentials"`
} `xml:"AssumeRoleWithWebIdentityResult"`
}
if err := xml.Unmarshal(body, &parsed); err != nil {
return nil, errors.New("awscreds: sts returned an unparseable response")
}
c := parsed.Result.Credentials
expires, err := parseExpiry(c.Expiration)
if err != nil {View on GitHub (pinned to 3ee70a1026)