AWS

AWS Credential Chain Debugger

AWS resolves credentials in a specific order. The first source that has valid credentials wins. This tool shows you exactly which source is winning and why your commands are authenticating the way they are.

6 credential sources 4 debug commands Runs in your browser

Everything runs in your browser. No credentials or commands are sent to any server.

How AWS Resolves Your Credentials

Click each step to see what AWS checks and what can go wrong

What AWS checks

The --profile flag passed directly on the command line

aws s3 ls --profile myprofile

Why it wins

Command line flags have the highest precedence. If you pass --profile on the command line it wins regardless of any environment variables or config files.

Gotcha

This is why adding --profile myprofile to a failing command often fixes it — you are bypassing whatever credential source was winning before.

If no credentials found here, check next source →

What AWS checks

These three environment variables in the current shell session

export AWS_ACCESS_KEY_ID=AKIAIOSFODNN7EXAMPLE export AWS_SECRET_ACCESS_KEY=wJalrXUtnFEMI export AWS_SESSION_TOKEN=token

Why it matters

Environment variables override config files but are overridden by command line flags. They persist for the entire shell session including any scripts or sub-processes you run.

Gotcha

This is the most common cause of using the wrong credentials. A leftover export from a previous assume-role session stays active until you unset all three variables or close the terminal.

unset AWS_ACCESS_KEY_ID unset AWS_SECRET_ACCESS_KEY unset AWS_SESSION_TOKEN
If no credentials found here, check next source →

What AWS checks

Cached SSO tokens stored at ~/.aws/sso/cache/

Why it matters

If you configured SSO with aws configure sso and the session has not expired the cached token is used here.

Gotcha

If your SSO session has expired AWS gives a confusing error rather than prompting you to log in again. The fix is to run aws sso login --profile yourprofile before any other command.

aws sso login --profile yourprofile
If no credentials found here, check next source →

What AWS checks

The profile named in AWS_PROFILE environment variable or the default profile

# ~/.aws/credentials [default] aws_access_key_id = AKIAIOSFODNN7EXAMPLE aws_secret_access_key = wJalrXUtnFEMI [myprofile] aws_access_key_id = AKIAI44QH8DHBEXAMPLE aws_secret_access_key = je7MtGbClwBF

Gotcha

The most common error is a profile that exists in ~/.aws/credentials but not in ~/.aws/config or vice versa. Run aws configure list-profiles to see what is actually configured.

aws configure list-profiles
If no credentials found here, check next source →

What AWS checks

A profile in ~/.aws/config that has both role_arn and source_profile set

[profile cross-account] role_arn = arn:aws:iam::123456789012:role/my-role source_profile = default region = us-east-1

Why it matters

This is the correct long-term way to work with assumed roles. AWS CLI automatically calls sts assume-role and refreshes temporary credentials without any manual export.

Gotcha

Most tutorials show the manual export method because it is faster to explain. But the source_profile approach is what AWS recommends because it handles token refresh automatically.

If no credentials found here, check next source →

What AWS checks

The metadata service at http://169.254.169.254/latest/meta-data/iam/security-credentials/

Why it matters

Only available when running on EC2, ECS, Lambda, or similar AWS compute. If you reach this step while running locally it means none of the previous sources found credentials.

Gotcha

If your application works on EC2 but fails locally this is why. Your EC2 instance has an IAM role attached. Your local machine does not.

Debug Your Credential Issue

Answer these questions to find which source is winning

Debug Commands

Run these in order when you cannot figure out which credentials AWS is using

Check active identity

aws sts get-caller-identity

Shows your Account ID, UserId, and ARN. The first command to run when anything is failing with auth errors.

Check credential sources

aws configure list

Shows where each configuration value is coming from — env variable, config file, or default. The source column tells you exactly what is winning.

List all profiles

aws configure list-profiles

If your profile is not in this list the error will be The config profile could not be found.

Check specific profile

aws sts get-caller-identity --profile myprofile

Replace myprofile with your profile name. If this fails the profile credentials are expired or misconfigured.

Common Scenarios

The most searched AWS credential problems and their fixes

My command works in one terminal but not another

You exported credentials in one terminal session that are not present in the other. Environment variables only exist in the shell where they were set.

Fix

Run env | grep AWS_ in both terminals to compare. Use a named profile in ~/.aws/config instead of environment variables for consistent behavior across sessions.

My application works on EC2 but fails on my laptop

Your EC2 instance has an IAM role attached via instance profile. Your laptop has no such role so credential resolution falls through all 6 steps and finds nothing.

Fix

Configure a local profile with aws configure --profile dev that has credentials matching the permissions your EC2 role has.

I assumed a role but AWS is using my old credentials

After running aws sts assume-role you did not export the returned credentials into environment variables or you are in a different shell session.

Fix

Export all three variables — AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, and AWS_SESSION_TOKEN — from the assume-role output. All three are required. Missing AWS_SESSION_TOKEN causes InvalidClientTokenId.

My credentials worked yesterday but fail today

Temporary credentials from an assumed role or SSO session have expired. Default session duration is 1 hour for assumed roles.

Fix

Run aws sts get-caller-identity to confirm the identity. Then run aws sso login --profile yourprofile for SSO or re-run the assume-role command for role-based credentials.

I get Access Denied but I can see the resource in the console

The IAM identity you are using via CLI is different from the identity you are logged in as in the console. Run aws sts get-caller-identity to confirm.

Fix

Run aws sts get-caller-identity and compare the returned ARN with the identity shown in the top right of the AWS console. They are likely different.

Understanding the AWS Credential Provider Chain

The AWS credential provider chain is the ordered list of places the AWS CLI and SDKs look for credentials before they give up and throw an error. It exists because AWS needs to support a huge range of environments with a single consistent tool. The same aws command needs to work correctly whether you are running it from a laptop with a named profile, a CI pipeline with environment variables injected by a secrets manager, or an EC2 instance with an IAM role attached and no credentials configured anywhere at all. Rather than forcing every environment to configure credentials the same way, AWS checks a fixed sequence of sources and uses the first one that resolves successfully.

This design choice is also why the chain causes so much confusion. Because every source is checked automatically and silently, there is no built in signal telling you which source actually won. Two engineers on the same team, running what looks like the exact same command, can authenticate as two completely different IAM identities because one of them has a leftover AWS_PROFILE variable set in their shell and the other does not. Nothing in the terminal output warns you this is happening. The command either works with the wrong permissions or fails with an error that gives no indication of which of the six sources was actually consulted.

Understanding the order of precedence turns this from a mystery into a checklist. Once you know that command line flags beat environment variables, which beat the SSO cache, which beat named profiles, which beat source_profile role assumption, which beat EC2 instance metadata, you can work through the list from the top down and find the source that is actually active in seconds. This is exactly what aws configure list is built to do. It prints, for every configuration value, which of these sources it came from, and that single command resolves a large share of AWS authentication problems on its own.

Engineers who internalize the credential chain also write more reliable infrastructure. They know to avoid exporting long lived credentials into a shell session that will outlive the task at hand. They design CI pipelines around short lived role assumption instead of static keys baked into environment variables. And when something breaks in production, they know to run aws sts get-caller-identity first, before touching anything else, because confirming which identity is actually active is always the fastest way to rule out half of the possible causes.

Why AWS Credential Errors Are So Confusing

AWS credential errors are hard to debug because the error message describes the symptom, not the cause, and the same symptom can come from any of six unrelated sources. An error like Unable to locate credentials or InvalidClientTokenId tells you that authentication failed, but it does not tell you which of the six steps in the chain actually produced that failure. You could be missing credentials entirely, or you could have credentials from the wrong source entirely overriding the ones you meant to use. The message looks identical either way.

The order of precedence makes this worse rather than better, because it means a valid, correctly configured credential source can be silently ignored. A named profile with the exact right permissions sitting in ~/.aws/config is completely irrelevant if an old AWS_ACCESS_KEY_ID environment variable from an unrelated project is still exported in that shell. The CLI is not broken in this scenario. It is doing exactly what it is designed to do, checking environment variables before config files, but the behavior looks like a bug to anyone who does not know the precedence order exists.

A second layer of confusion comes from temporary credentials. SSO sessions and assumed roles both expire, usually after an hour, and AWS does not proactively warn you when that happens. The command that worked five minutes ago starts failing with ExpiredToken or a similarly generic error, with no obvious link back to the fact that a clock somewhere quietly ran out. Engineers who do not know to check session expiry first often spend far longer investigating IAM policies or network issues than the actual problem requires.

The mental model that resolves most of this confusion is to stop asking why this is failing and start asking which of the six sources is currently winning. That reframes debugging from an open ended search into a short, ordered checklist: check command line flags, then environment variables, then the SSO cache, then named profiles, then source_profile role assumption, then instance metadata. Running aws configure list and aws sts get-caller-identity together answers that question directly, which is why those two commands resolve the overwhelming majority of AWS credential issues in practice.

Frequently Asked Questions