JuliusBrussee/caveman · error
awscreds: build request
Error message
awscreds: build %s request: %w
What it means
imdsGet wraps an error from http.NewRequestWithContext when building one of the two IMDS metadata GETs (role name, then credentials), labeled by the what parameter (e.g. "imds role", "imds credentials"). The library throws this when the endpoint URL is unparseable or the context is already dead.
Solutions
- Inspect the wrapped %w cause: fix net/url parse errors by correcting the endpoint; fix context errors by increasing the timeout.
- Set AWS_EC2_METADATA_SERVICE_ENDPOINT to a plain absolute http(s) URL with no extra path junk.
- Reuse a single healthy context with sufficient deadline for the whole IMDS sequence.
- Fall back to the default endpoint by unsetting the env var.
Example fix
// before ctx, cancel := context.WithTimeout(ctx, time.Microsecond) // dead before GETs // after ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
Defensive patterns
Strategy: try-catch
Validate before calling
deadline, ok := ctx.Deadline()
if !ok || time.Until(deadline) < 2*time.Second {
return errors.New("context deadline too tight for IMDS token+get sequence")
} Try / catch
if err != nil {
var urlErr *url.Error
if errors.As(err, &urlErr) && errors.Is(urlErr.Err, context.DeadlineExceeded) {
// retry with a fresh, longer-lived context
}
} Prevention
- Use one context with adequate budget for the full token+role+creds sequence
- Don't reuse an already-canceled context across provider calls
- Keep the endpoint env var free of control characters
When it happens
Trigger: The role-name or credentials URL derived from the IMDS base (base + /latest/meta-data/iam/security-credentials/...) is malformed, or ctx was canceled between the token fetch and the GET.
Common situations: Endpoint env var with trailing slash handled but other junk characters present; context timeout fired mid-sequence; custom endpoint missing scheme.
Understand the failure class
Background: "Invalid URL" errors: why new URL(), URI.parse, and reqwest::Url reject your string — missing scheme, whitespace, and bad path format — this error's family across 39 libraries.
Related errors
- awscreds: build imds token request
- awscreds: request failed
- awscreds: AWS_EC2_METADATA_SERVICE_ENDPOINT is not a valid…
- awscreds: build container credentials request
- awscreds: no AWS credentials found (env, web identity…
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/b4e34ea51593d475.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/awscreds/awscreds.go:594
role = line
break
}
}
if role == "" {
return nil, errors.New("awscreds: no instance profile role attached")
}
credBody, err := p.imdsGet(ctx, base+"/latest/meta-data/iam/security-credentials/"+url.PathEscape(role), token, "imds credentials")
if err != nil {
return nil, err
}
return credentialsFromJSON(credBody, "imds")
}
func (p *Provider) imdsGet(ctx context.Context, endpoint, token, what string) ([]byte, error) {
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
if err != nil {
return nil, fmt.Errorf("awscreds: build %s request: %w", what, err)
}
req.Header.Set("X-aws-ec2-metadata-token", token)
return p.doJSON(p.link, req, what)
}
// doJSON performs one attempt and returns the bounded body. A non-2xx response
// is reported by status only: a metadata body holds credential material.
func (p *Provider) doJSON(client *http.Client, req *http.Request, what string) ([]byte, error) {
resp, err := client.Do(req)
if err != nil {
return nil, fmt.Errorf("awscreds: %s request failed: %w", what, err)
}
defer resp.Body.Close()
body, err := io.ReadAll(io.LimitReader(resp.Body, maxBody))
if err != nil {
return nil, fmt.Errorf("awscreds: read %s response: %w", what, err)
}
if resp.StatusCode < 200 || resp.StatusCode > 299 {View on GitHub (pinned to 3ee70a1026)