JuliusBrussee/caveman · error
awscreds: sts assume role with web identity failed
Error message
awscreds: sts assume role with web identity failed: %w
What it means
After building the AssumeRoleWithWebIdentity request, fromWebIdentity executes it via the STS HTTP client. A transport-level failure (DNS, TCP connect, TLS, timeout, context cancellation) is wrapped with this message. The library is careful that the wrapped transport error carries the request URL but never the form body, so the web identity token is not leaked into the error text.
Solutions
- Confirm network egress to the STS endpoint (curl -v https://sts.<region>.amazonaws.com) from the same environment; add a VPC endpoint for STS if egress is blocked
- Unwrap with errors.As(*url.Error) to see the underlying cause (timeout vs DNS vs TLS) and fix accordingly
- Check proxy env vars (HTTPS_PROXY) and certificate bundles that could break TLS
- Retry with backoff for transient timeouts; verify the context deadline isn't too short
Example fix
// before
creds, err := awscreds.Credentials(ctx, p) // transport error, ctx has 2s deadline
// after
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
defer cancel()
creds, err := awscreds.Credentials(ctx, p)
if err != nil {
var ue *url.Error
if errors.As(err, &ue) { log.Printf("sts transport: %v", ue.Err) }
} Defensive patterns
Strategy: retry
Validate before calling
// preflight connectivity before credential fetch
conn, err := net.DialTimeout("tcp", "sts.amazonaws.com:443", 3*time.Second)
if err != nil { return fmt.Errorf("no egress to STS: %w", err) }
conn.Close() Type guard
func isTransportFailure(err error) bool {
var ue *url.Error
return errors.As(err, &ue) && strings.Contains(err.Error(), "sts assume role with web identity failed")
} Try / catch
var creds *awscreds.Result
var err error
for attempt := 0; attempt < 3; attempt++ {
creds, err = awscreds.Credentials(ctx, p)
if err == nil || !isTransportFailure(err) { break }
select {
case <-time.After(time.Duration(1<<attempt) * 200 * time.Millisecond):
case <-ctx.Done():
return ctx.Err()
}
} Prevention
- Open VPC endpoints (com.amazonaws.<region>.sts) in private clusters
- Set a generous context timeout (10s+) for the credential fetch
- Check HTTPS_PROXY/CA bundles that can break TLS to STS
- Log errors.As(*url.Error).Err to distinguish DNS vs timeout vs TLS
When it happens
Trigger: p.sts.Do(req) returns a *url.Error: STS endpoint unreachable, DNS failure, TLS handshake failure, request timeout, or ctx canceled mid-request while assuming a role via AWS_WEB_IDENTITY_TOKEN_FILE/AWS_ROLE_ARN.
Common situations: EKS pods without network egress to sts.<region>.amazonaws.com (missing VPC endpoint or NAT); corporate proxy blocking the call; STS regional endpoint typo; DNS failures in restricted clusters; slow IMDS-adjacent setups causing context timeouts.
Related errors
- awscreds: build sts request
- awscreds: read sts response
- awscreds: sts assume role with web identity: http
- awscreds: read response
- awscreds: : http
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/41524631e34861b3.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/awscreds/awscreds.go:339
}
form := url.Values{
"Action": {"AssumeRoleWithWebIdentity"},
"Version": {"2011-06-15"},
"RoleArn": {roleARN},
"RoleSessionName": {sessionName},
"WebIdentityToken": {token},
"DurationSeconds": {"3600"},
}
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"`View on GitHub (pinned to 3ee70a1026)