Report #60856
[bug\_fix] botocore.exceptions.NoCredentialsError: Unable to locate credentials
If running in a container on EC2 \(EKS, ECS, or self-managed Docker\), increase the IMDSv2 hop limit to 2 using the AWS CLI or Console: \`aws ec2 modify-instance-metadata-options --instance-id i-12345 --http-put-response-hop-limit 2 --http-endpoint enabled\`. If using Terraform, set \`http\_put\_response\_hop\_limit = 2\` in the \`metadata\_options\`. The fix works because IMDSv2 uses a PUT request to get a token, and that token is returned via the HTTP PUT response headers; by default, the hop limit is 1 \(local only\). When a container makes the request via the Docker bridge network, the hop count increments to 2. If the limit is 1, the metadata service drops the packet, and the SDK receives no credentials, falling back to the next provider \(which often fails\), resulting in NoCredentialsError.
Journey Context:
You have a microservice running in a Docker container on an EC2 instance \(or EKS node\). The container uses the AWS SDK \(Boto3, AWS SDK for Java, etc.\) to access S3 or DynamoDB. The EC2 instance has an IAM Role attached with the necessary permissions. You SSH onto the host and run \`aws s3 ls\`—it works. You exec into the Docker container and run the same command or your application—it fails with \`NoCredentialsError: Unable to locate credentials\`. You check the environment variables inside the container—no \`AWS\_ACCESS\_KEY\_ID\`. You check \`~/.aws/credentials\` inside the container—it's empty. You realize the container should be using the EC2 Instance Metadata Service \(IMDS\) to get credentials via the IAM role. You try \`curl http://169.254.169.254/latest/meta-data/iam/security-credentials/\` from inside the container—it hangs or returns nothing. You try the same from the host—it works. You research and find that AWS introduced IMDSv2 \(Instance Metadata Service version 2\) which requires a token obtained via a PUT request with a hop limit. The default hop limit is 1. Because the Docker network adds a hop, the container's request is dropped. You check the instance metadata options using \`aws ec2 describe-instances --instance-ids i-xxx --query 'Reservations\[\].Instances\[\].MetadataOptions'\` and see \`"HttpPutResponseHopLimit": 1\` and \`"HttpTokens": "required"\`. You modify the instance to set the hop limit to 2 using the CLI or by modifying the launch template. The container immediately starts retrieving credentials from IMDS and the \`NoCredentialsError\` disappears.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-20T08:37:54.002452+00:00— report_created — created