Skip to main content

Unable to Locate Credentials: Fix the AWS CLI and boto3 Error

Fix `Unable to locate credentials` in the AWS CLI and the boto3 NoCredentialsError. Diagnose the credential chain with aws configure list instead of guessing.

8 min readUpdated August 2026

If the AWS CLI stops with Unable to locate credentials, it did not fail to reach AWS — it never tried. The CLI walked its entire credential chain, found nothing usable, and gave up before signing a request.

$ aws s3 ls
Unable to locate credentials. You can configure credentials by running "aws configure".

Python users see the same failure from botocore:

botocore.exceptions.NoCredentialsError: Unable to locate credentials

The single most useful thing you can do is stop guessing and ask the CLI what it found:

aws configure list

That prints every setting alongside the source it came from, which tells you precisely which stage of the chain is empty.

Why This Happens

The AWS CLI looks for credentials in a fixed precedence order, and stops at the first stage that yields a complete set. The documented order is:

  1. Command line options (--profile, --region)
  2. Environment variables
  3. Assumed role configuration
  4. Assumed role with web identity
  5. IAM Identity Center (~/.aws/config, populated by aws configure sso)
  6. The credentials file — ~/.aws/credentials, or C:\Users\{USERNAME}\.aws\credentials on Windows
  7. A custom credential process
  8. The config file — ~/.aws/config
  9. Container credentials (ECS task roles)
  10. EC2 instance profile credentials, delivered through the instance metadata service

Unable to locate credentials means all ten came up empty. Critically, this is not a permissions problem. No IAM policy, bucket policy, or SCP can cause it, and none can fix it. Adding permissions in response to this error grants real access while leaving the actual cause untouched.

Fix 1: Configure a Profile (No Credentials Set Up Yet)

If aws configure list shows every value as <not set>, nothing is configured. Prefer short-term credentials:

aws configure sso
aws sso login --profile my-profile

IAM Identity Center issues credentials that expire automatically, so a leaked value has a short useful life. If you must use long-term IAM user keys, aws configure writes them to ~/.aws/credentials — but treat that as a fallback, and pair it with a regular key rotation routine.

Fix 2: You Are Using the Wrong Profile

aws configure list shows the active profile. If your credentials live under a named profile, the CLI will not find them unless you say so:

aws s3 ls --profile dev
export AWS_PROFILE=dev          # applies to the rest of the shell session
aws configure list-profiles     # every profile the CLI can see

Fix 3: The Profile Header Syntax Is Wrong

This trips up nearly everyone once. The two files use different section header formats:

# ~/.aws/credentials  — no prefix
[dev]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

# ~/.aws/config  — "profile" prefix required
[profile dev]
region = us-east-1
output = json

[default] is the one exception: it never takes the profile prefix in either file. A [profile dev] header inside credentials produces a profile the CLI silently ignores.

Advertisement

Fix 4: A Different User or Environment Is Running the Command

Credentials live under $HOME. Anything that changes HOME hides them:

  • sudo runs as root, whose home is /root, not yours.
  • cron and systemd start with a minimal environment.
  • Docker containers inherit neither your environment nor your home directory.

Point the SDK at the files explicitly when you cannot avoid this:

export AWS_CONFIG_FILE=/home/deploy/.aws/config
export AWS_SHARED_CREDENTIALS_FILE=/home/deploy/.aws/credentials

On ECS or EKS, the better answer is a task role or IRSA — the container credentials stage of the chain then supplies short-term credentials with no files at all.

Fix 5: Environment Variables Are Incomplete

The environment stage requires the whole set, not part of it:

export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE
export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY
export AWS_SESSION_TOKEN=...        # required for temporary credentials only

Setting only the key ID skips the stage entirely. If you assumed a role and omitted AWS_SESSION_TOKEN, you will get a signature error rather than this one — but the missing-variable habit causes both.

Fix 6: EC2 Instance Metadata Is Unreachable

On EC2 the last stage of the chain queries the Instance Metadata Service. It fails when no instance profile is attached, when the metadata endpoint is firewalled, or when the hop limit is 1 and the call originates inside a container (the extra network hop consumes the budget). Raise it to 2 for containerised workloads, and confirm the instance profile is attached in the EC2 console.

Verify the Fix

aws sts get-caller-identity
{
    "UserId": "AIDACKCEVSQ6C2EXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/dev"
}

This is the cheapest authenticated call in AWS and requires no permissions of its own, so a JSON response proves the CLI both found credentials and signed a request successfully. Once it works, ordinary commands such as those in our S3 CLI cheat sheet will work too.

Prevent It From Recurring

  • Use IAM Identity Center rather than long-term keys. Short-term credentials expire on their own, which limits the damage from a leak.
  • Never commit credentials. Keep .aws/ and any .env out of version control.
  • Give hosts roles, not files. EC2 instance profiles, ECS task roles, and IRSA remove credential files from the problem entirely.
  • Set AWS_PROFILE in your shell profile when you work with one account most of the time, so the default is never ambiguous.
  • Put aws sts get-caller-identity at the top of deployment scripts. Failing immediately with a clear identity check beats failing halfway through a deployment.

Frequently Asked Questions

Find answers to common questions

It means the CLI worked through every credential source it knows about — command line options, environment variables, assumed roles, IAM Identity Center, the credentials and config files, and instance metadata — and found nothing usable in any of them. It is not a permissions error. The CLI never reached AWS, so no policy, role, or bucket setting is involved.

Run 'aws configure list' first. It prints each setting with the source it came from, so you can see exactly which stage of the chain is empty. If everything shows as not set, configure a profile with 'aws configure sso' for short-term credentials. Then confirm with 'aws sts get-caller-identity'.

It is the boto3 and botocore equivalent of the same failure, printed as 'botocore.exceptions.NoCredentialsError: Unable to locate credentials'. Python SDKs use the same credential chain as the CLI, so the cause and the fix are identical. If the CLI works but your script does not, the two are running as different users or with different environment variables.

Because those run with a different HOME and a stripped environment, so ~/.aws/credentials is never found. Set the full path explicitly with AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE in the unit or crontab, or better, attach an IAM role to the host so no file is needed at all.

Containers do not inherit your shell environment or your home directory. Pass credentials in explicitly, or on ECS and EKS use a task role or IRSA so the SDK picks up container credentials automatically. Mounting ~/.aws read-only works for local development but should not be used in production images.

No, and you should not. This error happens before any request is signed or sent, so no IAM policy can affect it. Attaching broader permissions in response to it grants real access without fixing anything. Permission problems produce an explicit AccessDenied message instead.

In ~/.aws/credentials the section header is just the profile name, like [dev]. In ~/.aws/config the same profile needs the word profile first, like [profile dev]. The single exception is [default], which never takes the prefix. Getting this backwards is one of the most common causes of the error.

Either no instance profile is attached to the instance, or the Instance Metadata Service is unreachable. A hop limit of 1 blocks IMDS from inside a container, and IMDSv2 requires a token request first. Test from the instance with 'aws sts get-caller-identity' and check the attached instance profile in the EC2 console.

No. The environment variable stage of the chain requires both AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY, plus AWS_SESSION_TOKEN when the credentials are temporary. A partially set trio is skipped, which is why the error can appear even though you exported something.

Run 'aws sts get-caller-identity'. It is the cheapest authenticated call available and it requires no permissions of its own. A JSON response containing UserId, Account, and Arn confirms the CLI both found credentials and successfully signed a request.