JuliusBrussee/caveman · error
awscreds: unsupported IMDS endpoint scheme
Error message
awscreds: unsupported IMDS endpoint scheme %q
What it means
Error from checkIMDSEndpoint: AWS_EC2_METADATA_SERVICE_ENDPOINT parsed as a URL but its scheme is neither https nor plain http (and http is only allowed for allowlisted plaintext hosts). Because this endpoint is dialled by the proxy-ignoring link client, non-conforming schemes are refused before any IMDSv2 token is attached.
Solutions
- Set the endpoint with an explicit scheme, e.g. http://169.254.169.254 or https://....
- Use the canonical endpoint http://169.254.169.254/latest unless you have a simulator.
- Unset AWS_EC2_METADATA_SERVICE_ENDPOINT to use the built-in default.
- Check for stray whitespace/characters corrupting the URL scheme.
Example fix
// before
os.Setenv("AWS_EC2_METADATA_SERVICE_ENDPOINT", "169.254.169.254/latest")
// after
os.Setenv("AWS_EC2_METADATA_SERVICE_ENDPOINT", "http://169.254.169.254/latest") Defensive patterns
Strategy: validation
Validate before calling
if ep := os.Getenv("AWS_EC2_METADATA_SERVICE_ENDPOINT"); ep != "" {
u, err := url.Parse(ep)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
return fmt.Errorf("AWS_EC2_METADATA_SERVICE_ENDPOINT must include an http(s) scheme: %q", ep)
}
} Try / catch
if err != nil && strings.Contains(err.Error(), "unsupported IMDS endpoint scheme") {
log.Fatal("set AWS_EC2_METADATA_SERVICE_ENDPOINT to e.g. http://169.254.169.254")
} Prevention
- Always prefix the endpoint with http:// or https://
- Trim whitespace from env values set programmatically
- Validate at config load time, not at first credential fetch
When it happens
Trigger: AWS_EC2_METADATA_SERVICE_ENDPOINT contains an unsupported or missing scheme (e.g. 'metadata.internal' with no scheme, or socks5://...), so url.Parse yields a scheme falling into the default branch.
Common situations: Forgetting the http:// prefix when setting the endpoint env var; pasting a proxy or socket URI into the metadata endpoint variable; IMDSv2-only tooling emitting exotic schemes.
Understand the failure class
Background: "Invalid URL" / "URL cannot be empty": fix the malformed or missing URL behind request-construction failures — this error's family across 50 libraries.
Related errors
- awscreds: unsupported container credentials scheme
- awscreds: AWS_EC2_METADATA_SERVICE_ENDPOINT is not a valid…
- awscreds: build container credentials request
- awscreds: build imds token request
- awscreds: build request
AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20).
Data as JSON: /api/errors/fe19fe95ac0e2b3a.
Report an issue: GitHub.
Appendix: source
Thrown at shared/platform/awscreds/awscreds.go:533
// checkIMDSEndpoint is checkContainerURI for AWS_EC2_METADATA_SERVICE_ENDPOINT.
// That variable was taken verbatim and then dialled with p.link — the client
// that deliberately ignores every proxy setting — so any host named there became
// a proxy-bypassing outbound request with the IMDSv2 token attached.
func checkIMDSEndpoint(raw string) error {
u, err := url.Parse(raw)
if err != nil || u.Host == "" {
return errors.New("awscreds: AWS_EC2_METADATA_SERVICE_ENDPOINT is not a valid URL")
}
switch u.Scheme {
case "https":
return nil
case "http":
if plaintextHostAllowed(u.Hostname(), imdsHosts) {
return nil
}
return fmt.Errorf("awscreds: refusing plaintext IMDS endpoint at host %q (allowed: loopback, 169.254.169.254, fd00:ec2::254)", u.Hostname())
default:
return fmt.Errorf("awscreds: unsupported IMDS endpoint scheme %q", u.Scheme)
}
}
func (p *Provider) fromIMDS(ctx context.Context) (*result, error) {
if strings.EqualFold(p.env("AWS_EC2_METADATA_DISABLED"), "true") {
return nil, nil
}
base := p.env("AWS_EC2_METADATA_SERVICE_ENDPOINT")
if base == "" {
base = defaultIMDSBase
}
if err := checkIMDSEndpoint(base); err != nil {
return nil, err
}
base = strings.TrimSuffix(base, "/")
// IMDSv2 only: a v1 fallback would leave the proxy vulnerable to the SSRF
// class the session token exists to close.View on GitHub (pinned to 3ee70a1026)