JuliusBrussee/caveman · error
awscreds: read sts response
Error message
awscreds: read sts response: %w
What it means
The STS AssumeRoleWithWebIdentity response body is read with io.ReadAll(io.LimitReader(resp.Body, maxBody)). If reading the body fails mid-stream — connection reset, unexpected EOF, context canceled while streaming — the error is wrapped as "awscreds: read sts response" and the credential fetch fails.
Solutions
- Retry the credential fetch with backoff — body-read resets are usually transient
- Extend the context deadline if ctx cancellation is the cause
- Check for proxies/LBs between the client and STS that truncate responses; test with curl against the same endpoint
- Ensure the STS endpoint is the official one (or a healthy compatible endpoint) rather than a flaky mirror
Example fix
// before
creds, err := awscreds.Credentials(ctx, p) // unexpected EOF during body read
// after
var creds *awscreds.Result
for i := 0; i < 3; i++ {
creds, err = awscreds.Credentials(ctx, p)
if err == nil || !strings.Contains(err.Error(), "read sts response") { break }
time.Sleep(time.Duration(1<<i) * 100 * time.Millisecond)
} Defensive patterns
Strategy: retry
Validate before calling
// no caller-side pre-check can prevent a mid-body reset; instead preflight the endpoint
resp, err := http.Head(stsEndpoint)
if err == nil { resp.Body.Close() } // ensures the path is at least reachable Type guard
func isBodyReadFailure(err error) bool {
return err != nil && strings.Contains(err.Error(), "read sts response")
} Try / catch
creds, err := awscreds.Credentials(ctx, p)
if isBodyReadFailure(err) {
// transient stream break: one retry is usually enough
time.Sleep(250 * time.Millisecond)
creds, err = awscreds.Credentials(ctx, p)
} Prevention
- Keep the context deadline longer than the expected STS round-trip
- Remove/bypass proxies that truncate streaming bodies
- Prefer official STS endpoints over mirrors behind flaky LBs
- Retry idempotent credential fetches on transient IO errors
When it happens
Trigger: io.ReadAll inside fromWebIdentity returns err after p.sts.Do succeeded: server closed the connection mid-body, TLS truncation, proxy dropped the stream, or ctx was canceled during the read.
Common situations: Flaky networks/NAT dropping long-lived connections; load balancers in front of a self-hosted STS terminating connections; aggressive context timeouts cutting the read short; intermediate proxies mangling the response.
Related errors
- awscreds: read response
- awscreds: sts assume role with web identity failed
- awscreds: build sts request
- awscreds: request failed
- awscreds: sts assume role with web identity: http
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/380f2e07cc8cf81d.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/awscreds/awscreds.go:344
"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"`
} `xml:"AssumeRoleWithWebIdentityResult"`
}
if err := xml.Unmarshal(body, &parsed); err != nil {
return nil, errors.New("awscreds: sts returned an unparseable response")
}View on GitHub (pinned to 3ee70a1026)