JuliusBrussee/caveman · error

awscreds: unsupported container credentials scheme

Error message

awscreds: unsupported container credentials scheme %q

What it means

checkContainerURI rejects a container credentials endpoint whose URL scheme is neither https nor http. The library only knows how to speak HTTP(S) to the ECS/EKS credentials service and refuses anything else.

Solutions

  1. Prefix the URI with an explicit http:// or https:// scheme.
  2. Use the standard ECS/EKS credentials endpoint format (http://169.254.170.2/v2/credentials).
  3. If you need a unix socket or non-HTTP transport, front it with a small local HTTP proxy on loopback.
  4. Unset the variable to fall back to the default container endpoint.

Example fix

// before
os.Setenv("AWS_CONTAINER_CREDENTIALS_FULL_URI", "169.254.170.2/v2/credentials")
// after
os.Setenv("AWS_CONTAINER_CREDENTIALS_FULL_URI", "http://169.254.170.2/v2/credentials")
Defensive patterns

Strategy: validation

Validate before calling

u, err := url.Parse(fullURI)
if err != nil || (u.Scheme != "http" && u.Scheme != "https") {
    return fmt.Errorf("AWS_CONTAINER_CREDENTIALS_FULL_URI must be http(s), got %q", fullURI)
}

Try / catch

if err != nil && strings.Contains(err.Error(), "unsupported container credentials scheme") {
    log.Fatal("add an explicit http:// or https:// scheme to AWS_CONTAINER_CREDENTIALS_FULL_URI")
}

Prevention

When it happens

Trigger: AWS_CONTAINER_CREDENTIALS_FULL_URI set with a scheme like socks5, unix, ftp, or a malformed scheme (e.g. '169.254.170.2' parsed with an empty scheme reaching the default branch).

Common situations: Copying a proxy URL into the credentials URI variable; omitting the scheme entirely so url.Parse yields an empty scheme; custom link-local protocols unsupported by this provider.

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


AI-assisted analysis of JuliusBrussee/caveman@3ee70a1026 (2026-09-20). Data as JSON: /api/errors/81119ca14b7cd9b7. Report an issue: GitHub.

Appendix: source

Thrown at shared/platform/awscreds/awscreds.go:511

// checkContainerURI applies the SDK rule for a caller-supplied credential
// endpoint: TLS anywhere, plaintext only to loopback or the fixed ECS/EKS
// credential addresses. Without it, AWS_CONTAINER_CREDENTIALS_FULL_URI is a
// request to hand a task role's Authorization token to an arbitrary host.
func checkContainerURI(raw string) error {
	u, err := url.Parse(raw)
	if err != nil {
		return errors.New("awscreds: AWS_CONTAINER_CREDENTIALS_FULL_URI is not a valid URL")
	}
	switch u.Scheme {
	case "https":
		return nil
	case "http":
		if plaintextHostAllowed(u.Hostname(), containerCredentialHosts) {
			return nil
		}
		return fmt.Errorf("awscreds: refusing plaintext container credentials endpoint at host %q (allowed: loopback, 169.254.170.2, 169.254.170.23, fd00:ec2::23)", u.Hostname())
	default:
		return fmt.Errorf("awscreds: unsupported container credentials scheme %q", u.Scheme)
	}
}

// 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

View on GitHub (pinned to 3ee70a1026)