{"record":{"id":"41524631e34861b3","repo":"JuliusBrussee/caveman","slug":"awscreds-sts-assume-role-with-web-identity-failed-w","errorCode":null,"errorMessage":"awscreds: sts assume role with web identity failed: %w","messagePattern":"awscreds: sts assume role with web identity failed: %w","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"shared/platform/awscreds/awscreds.go","lineNumber":339,"sourceCode":"\t}\n\tform := url.Values{\n\t\t\"Action\":           {\"AssumeRoleWithWebIdentity\"},\n\t\t\"Version\":          {\"2011-06-15\"},\n\t\t\"RoleArn\":          {roleARN},\n\t\t\"RoleSessionName\":  {sessionName},\n\t\t\"WebIdentityToken\": {token},\n\t\t\"DurationSeconds\":  {\"3600\"},\n\t}\n\treq, err := http.NewRequestWithContext(ctx, http.MethodPost, p.stsEndpoint, strings.NewReader(form.Encode()))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: build sts request: %w\", err)\n\t}\n\treq.Header.Set(\"Content-Type\", \"application/x-www-form-urlencoded\")\n\treq.Header.Set(\"Accept\", \"application/xml\")\n\tresp, err := p.sts.Do(req)\n\tif err != nil {\n\t\t// A transport error can carry the request URL but never the form body.\n\t\treturn nil, fmt.Errorf(\"awscreds: sts assume role with web identity failed: %w\", err)\n\t}\n\tdefer resp.Body.Close()\n\tbody, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"awscreds: read sts response: %w\", err)\n\t}\n\tif resp.StatusCode != http.StatusOK {\n\t\treturn nil, fmt.Errorf(\"awscreds: sts assume role with web identity: http %d%s\", resp.StatusCode, stsErrorCode(body))\n\t}\n\tvar parsed struct {\n\t\tXMLName xml.Name `xml:\"AssumeRoleWithWebIdentityResponse\"`\n\t\tResult  struct {\n\t\t\tCredentials struct {\n\t\t\t\tAccessKeyID     string `xml:\"AccessKeyId\"`\n\t\t\t\tSecretAccessKey string `xml:\"SecretAccessKey\"`\n\t\t\t\tSessionToken    string `xml:\"SessionToken\"`\n\t\t\t\tExpiration      string `xml:\"Expiration\"`\n\t\t\t} `xml:\"Credentials\"`","sourceCodeStart":321,"sourceCodeEnd":357,"githubUrl":"https://github.com/JuliusBrussee/caveman/blob/3ee70a102609e550bd2e68004bf5990a9341c851/shared/platform/awscreds/awscreds.go#L321-L357","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\ncreds, err := awscreds.Credentials(ctx, p) // transport error, ctx has 2s deadline\n// after\nctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)\ndefer cancel()\ncreds, err := awscreds.Credentials(ctx, p)\nif err != nil {\n    var ue *url.Error\n    if errors.As(err, &ue) { log.Printf(\"sts transport: %v\", ue.Err) }\n}","handlingStrategy":"retry","validationCode":"// preflight connectivity before credential fetch\nconn, err := net.DialTimeout(\"tcp\", \"sts.amazonaws.com:443\", 3*time.Second)\nif err != nil { return fmt.Errorf(\"no egress to STS: %w\", err) }\nconn.Close()","typeGuard":"func isTransportFailure(err error) bool {\n    var ue *url.Error\n    return errors.As(err, &ue) && strings.Contains(err.Error(), \"sts assume role with web identity failed\")\n}","tryCatchPattern":"var creds *awscreds.Result\nvar err error\nfor attempt := 0; attempt < 3; attempt++ {\n    creds, err = awscreds.Credentials(ctx, p)\n    if err == nil || !isTransportFailure(err) { break }\n    select {\n    case <-time.After(time.Duration(1<<attempt) * 200 * time.Millisecond):\n    case <-ctx.Done():\n        return ctx.Err()\n    }\n}","preventionTips":["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"],"tags":["aws","sts","network","http"],"backgroundTag":"oauth-token-exchange-failed","analyzedSha":"3ee70a102609e550bd2e68004bf5990a9341c851","analyzedAt":"2026-09-20T15:53:39.229Z","contentChangedAt":"2026-09-20T15:53:39.229Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}