JuliusBrussee/caveman · error

awscreds: no AWS credentials found (env, web identity…

Error message

awscreds: no AWS credentials found (env, web identity, container, IMDS)

What it means

The awscreds Provider walks a chain of credential sources — static env vars, web identity (IRSA/STS), container credentials (ECS/EKS endpoint), and EC2 IMDS. This terminal error means every source returned nothing usable, so no AWS credentials exist in the process and SigV4 signing cannot proceed.

Solutions

  1. Export AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY (and AWS_SESSION_TOKEN for temporary keys) in the proxy process
  2. Attach an IAM role: instance profile, ECS task role, or Kubernetes service account with IRSA
  3. Verify the metadata service is reachable if relying on IMDS (no AWS_EC2_METADATA_DISABLED, no blocked link-local traffic)
  4. If using Bedrock, consider a Bedrock bearer API key instead of SigV4

Example fix

// before (empty env)
$ env | grep AWS_   # nothing
// after
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
Defensive patterns

Strategy: validation

Validate before calling

func hasAnyAWSCreds() bool {
	if os.Getenv("AWS_ACCESS_KEY_ID") != "" && os.Getenv("AWS_SECRET_ACCESS_KEY") != "" { return true }
	if os.Getenv("AWS_WEB_IDENTITY_TOKEN_FILE") != "" { return true }
	if os.Getenv("AWS_CONTAINER_CREDENTIALS_RELATIVE_URI") != "" || os.Getenv("AWS_CONTAINER_CREDENTIALS_FULL_URI") != "" { return true }
	return os.Getenv("AWS_EC2_METADATA_DISABLED") != "true"
}

Try / catch

creds, err := provider.Credentials(ctx)
if err != nil {
	if strings.Contains(err.Error(), "no AWS credentials found") {
		// fall back to bearer API key or abort with setup guidance
	}
	return err
}

Prevention

When it happens

Trigger: Calling Credentials() in an environment with no env keys, no web identity token file, no AWS_CONTAINER_CREDENTIALS_RELATIVE/FULL_URI, and no reachable IMDS — e.g. local dev or a container without any role attached.

Common situations: Running the proxy locally outside AWS with no keys exported; Kubernetes pod missing an IRSA annotation; ECS task without a task role; CI runners with no AWS env; firewall blocking 169.254.169.254.

Related errors


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

Appendix: source

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

}

func (p *Provider) fetch(ctx context.Context) (*result, error) {
	for _, source := range []func(context.Context) (*result, error){
		p.fromEnv, p.fromWebIdentity, p.fromContainer, p.fromIMDS,
	} {
		res, err := source(ctx)
		if err != nil {
			return nil, err
		}
		if res == nil {
			continue
		}
		if !res.creds.Valid() {
			return nil, fmt.Errorf("awscreds: %s returned incomplete credentials", res.source)
		}
		return res, nil
	}
	return nil, errors.New("awscreds: no AWS credentials found (env, web identity, container, IMDS)")
}

func (p *Provider) env(name string) string { return strings.TrimSpace(p.getenv(name)) }

// fromEnv reads static keys. A half-configured pair is an error, not a skip:
// the operator clearly meant to sign as these keys, and falling through would
// silently sign as whatever ambient role the host carries — a different
// principal, bill, and CloudTrail identity — with no disclosure. A lone
// AWS_SESSION_TOKEN is not a pair and does not trigger this.
func (p *Provider) fromEnv(context.Context) (*result, error) {
	access, secret := p.env("AWS_ACCESS_KEY_ID"), p.env("AWS_SECRET_ACCESS_KEY")
	if access == "" && secret == "" {
		return nil, nil
	}
	if access == "" || secret == "" {
		return nil, errors.New("awscreds: AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY must both be set")
	}
	return &result{

View on GitHub (pinned to 3ee70a1026)