AWS Error Guide: 'Unable to locate credentials' Missing Credential Chain
Fix the AWS CLI 'Unable to locate credentials' error: configure profiles, environment variables, instance roles, and the credential provider chain correctly.
- #aws
- #troubleshooting
- #errors
- #credentials
Exact Error Message
Unable to locate credentials. You can configure credentials by running "aws configure".
From SDKs the same condition surfaces as NoCredentialsError, Unable to load AWS credentials from any provider in the chain, or CredentialsProviderError. The request never reaches AWS — the failure happens locally before signing.
What the Error Means
Every AWS API call must be signed with credentials. The CLI and SDKs search for those credentials through an ordered credential provider chain: environment variables, then the shared credentials file, then the shared config file, then container/IRSA credentials, then the EC2 instance metadata service. Each provider is tried in turn, and the first one that returns a usable set of credentials wins. Unable to locate credentials means the chain was walked end to end and no provider supplied any credentials at all — every link came up empty.
This is distinct from a permissions error or an expired token. There are simply no credentials to sign with, so the request was never even constructed, let alone sent to AWS. That is why the message is generated locally and arrives almost instantly: nothing reached the network. The practical consequence is that you should look at how the host or process is configured to obtain credentials, not at IAM policies or trust relationships, which only come into play once a request is actually signed and transmitted.
Common Causes
- No
aws configurerun. A fresh machine has no~/.aws/credentialsfile, so the shared-credentials provider has nothing to read and every other provider is empty too. - Wrong or missing profile. A command uses
--profile prodbut that profile is not defined, orAWS_PROFILEpoints at a nonexistent profile. A single typo in the profile name is enough to send the chain looking in a place that does not exist. HOMEnot set. In cron jobs, systemd units, or containers,HOMEmay be unset so the CLI cannot expand~/.aws/and skips the file-based providers entirely, even when the files are present on disk.- Running as a different user.
sudoor a service account has its own home directory with no credentials file, so credentials that work for your login user are invisible to the privileged context. - Instance metadata unreachable. On EC2/ECS, IMDS is blocked by a firewall rule, the hop limit is too low for a container, or no instance role is attached, leaving the last link in the chain empty.
- IRSA misconfigured. In EKS, the service account lacks the
eks.amazonaws.com/role-arnannotation or the projected token volume is not mounted, so the web-identity provider never activates for the pod. - Empty environment. A container expected
AWS_ACCESS_KEY_ID/AWS_SECRET_ACCESS_KEYto be injected at runtime, but the orchestrator or secret store never supplied them, leaving the environment provider blank.
How to Reproduce the Error
Run any command with an empty credential chain by pointing config at an empty directory:
env -i HOME=/tmp/empty-home AWS_CONFIG_FILE=/tmp/none \
AWS_SHARED_CREDENTIALS_FILE=/tmp/none aws sts get-caller-identity
Unable to locate credentials. You can configure credentials by running "aws configure".
A common real-world reproduction is invoking the CLI from a systemd service where HOME is unset and no instance role is attached.
Diagnostic Commands
Ask the CLI exactly where it is looking and what it found:
aws configure list
The output’s Type column shows the source (env, shared-credentials-file, iam-role) — a blank value means nothing was found there. List defined profiles:
aws configure list-profiles
Confirm which profile is selected and whether the home directory resolves:
echo "${AWS_PROFILE:-default}" && echo "$HOME"
On EC2, test whether the instance metadata service is reachable and which role is attached (read-only):
aws sts get-caller-identity
Verify a specific profile resolves end to end:
aws sts get-caller-identity --profile prod
Step-by-Step Resolution
-
Run
aws configure listto see which providers are empty. The fix depends entirely on where you expected credentials to come from, so always start here rather than guessing — theTypecolumn points straight at the missing link. -
For a workstation, set up a profile:
aws configure --profile devThen select it with
AWS_PROFILE=devor--profile dev. -
For environment-variable credentials, confirm all three (or two) are exported in the same shell that runs the CLI — a
sudoor subshell may not inherit them. Variables set in an interactive profile often vanish under automation, so verify them in the exact context that runs the command. -
For services and cron, export
HOME(or setAWS_SHARED_CREDENTIALS_FILE/AWS_CONFIG_FILEto absolute paths) in the unit so~/.aws/resolves for the service user. Absolute paths are the most robust fix because they do not depend onHOMEbeing present at all. -
For EC2, attach an instance profile and confirm the IMDS hop limit allows your runtime (containers often need a hop limit of 2 because the extra network namespace adds a hop). Then
aws sts get-caller-identityshould resolve viaiam-role. -
For EKS, annotate the service account with the role ARN and confirm the projected token volume is mounted; IRSA then populates the chain automatically without any static secret living in the pod.
-
Verify with
aws sts get-caller-identity— a returned ARN confirms the chain now resolves end to end, which is the only proof that the underlying configuration is correct.
Prevention and Best Practices
- Standardize on named profiles or instance/IRSA roles rather than ad-hoc environment exports that vanish across shells and users. Configuration that lives in a file or attached role survives reboots, new sessions, and privilege changes in a way that exported variables never do.
- In systemd units, always set
Environment=HOME=/root(or the service user’s home) or absoluteAWS_*_FILEpaths, because the minimal environment systemd provides almost never includes theHOMEthe CLI needs. - On EC2, prefer instance roles over baked-in keys, and set the IMDS hop limit to 2 for containerized workloads so the metadata endpoint stays reachable from inside the container network namespace.
- In EKS, use IRSA or Pod Identity so pods receive credentials automatically and rotate without static secrets, removing an entire class of leaked-key and stale-secret incidents.
- Add a startup health check that runs
aws sts get-caller-identityand fails fast with a clear message if the chain is empty, turning a confusing mid-run failure into an obvious boot-time error. - Never commit credentials to images or repos; rely on the provider chain so secrets are supplied at runtime rather than frozen into an artifact.
Related Errors
The config profile (X) could not be found— the named profile does not exist, a narrower case of a missing source.InvalidClientTokenId— credentials were found but the access key is unknown or disabled.ExpiredToken— credentials were found but the temporary session has lapsed.AccessDenied— credentials resolved and are valid but lack permission for the action.
Frequently Asked Questions
Why does it work in my terminal but fail in cron? Cron runs with a deliberately minimal environment — HOME and your interactive exports are usually absent, so the file-based providers cannot find ~/.aws/. Set HOME or absolute AWS_*_FILE paths explicitly in the crontab or job definition.
My EC2 instance has a role but still fails — why? Check the IMDS hop limit and that the metadata endpoint is not blocked by iptables, a security tool, or a sidecar; containers commonly need a hop limit of 2 because the extra namespace consumes one hop. Confirm the role is actually attached to the instance, not just defined.
What order does the chain search? Environment variables, shared credentials file, shared config file, container/IRSA credentials, then EC2 instance metadata. The first provider with credentials wins, which is why a stray environment variable can quietly override the profile you intended to use.
Does aws configure list make a network call? No. It only inspects local configuration sources, making it completely safe for fast triage even in locked-down environments where outbound traffic is restricted.
How is this different from AccessDenied? Unable to locate credentials means no credentials at all and the request never left the host; AccessDenied means valid credentials reached AWS but lacked permission for the action. They sit at opposite ends of the request lifecycle, so the fixes share nothing in common.
Can a typo in the profile name cause this? Yes. If AWS_PROFILE or --profile names a profile that does not exist, the chain treats that source as empty and reports it could not locate credentials. Run aws configure list-profiles to confirm the exact spelling. See more AWS guides.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.