AWS "InvalidClientTokenId: The Security Token Included in the Request Is Invalid", Fixed: Stale Environment Variables, AKIA vs ASIA Session Tokens, Opt-In Regions, LocalStack and get-caller-identity
"An error occurred (InvalidClientTokenId) when calling the GetCallerIdentity operation: The security token included in the request is invalid" means AWS does not accept the access key ID your request was signed with: the key does not exist, was deleted or deactivated, belongs to a different AWS partition, is a temporary key sent without its matching session token, or is being used in a Region your account has not enabled. The fastest way in is two commands: aws configure list shows which credentials the CLI actually picked up and where they came from, and aws sts get-caller-identity tests them. Here is the part that wastes the most time: AWS returns the identical sentence for at least three different mistakes. A key that does not exist, a temporary key missing its session token, and a brand-new key with an old session token still attached all return the same code, the same message and HTTP 403. The error cannot tell you which one you have; the order you check things in can. And the most common cause is not a bad key at all: an old environment variable quietly overriding the profile you just fixed.
Ethan, Jake's developer friend, rotated the access key for the shop's backup script on Monday, as the security reminder told him to. He pasted the new key into aws configure, ran the script, and got "The security token included in the request is invalid." He deleted and recreated the key twice more, then pasted it again, slower. Same error. Jake watched the third attempt and asked the question that solved it: "Is the computer even reading the file you keep editing?" It was not. A key from a test six months earlier was still sitting in a Windows environment variable, and environment variables win.
New to AWS credentials? Our plain-English IAM guide explains users, roles and access keys in about ten minutes. You can follow this page without it: every command below is copy-paste ready for Windows, macOS and Kali Linux.
What the error actually means
Every request to AWS is signed with two values: an access key ID (the public half, a 20-character string starting with AKIA or ASIA) and a secret access key (the private half, used to compute the signature). Temporary credentials add a third value, the session token, a long string that proves the temporary key is still valid.
When a request arrives, AWS first looks up the access key ID. InvalidClientTokenId is what you get when that lookup fails, or when the key and its session token do not belong together. It is decided before AWS even checks your signature, which is why the secret key is almost never the cause. A wrong secret with a valid key produces a different error, SignatureDoesNotMatch.
The two key prefixes are your first clue, so learn them:
- AKIA... is a long-term access key that belongs to an IAM user (or, rarely, the root user). It works on its own, with no session token, until someone deletes or deactivates it.
- ASIA... is a temporary access key from AWS STS: from
assume-role, IAM Identity Center (SSO), an EC2 instance role, a Lambda role orget-session-token. It only works together with its own session token, and only until it expires.
The error message says "security token," which makes people hunt for a token they never used. Here, "security token" means your whole credential set. For an AKIA key, the useful reading is "AWS does not recognize this access key ID."
"So it's not saying my password is wrong," Jake said. "It's saying it has never heard of me." Ethan nodded. "Or that it has, and I showed it someone else's badge."
The two-minute diagnosis
The error message is the same for every cause, so you diagnose by checking what your request is actually sending. Run these in order.
- See which credentials are in use, and where they come from:
aws configure list
Name Value Type Location
---- ----- ---- --------
profile <not set> None None
access_key ****************7Q2X env
secret_key ****************h9Ka env
region us-east-1 config-file ~/.aws/config
Read the Type column. env means environment variables; shared-credentials-file means ~/.aws/credentials; iam-role means an EC2 instance profile; sso means IAM Identity Center. Then compare the last four characters of access_key with the key you think you are using. If they differ, you have found your problem without touching AWS at all.
- Test the credentials with the one call that needs no permissions:
aws sts get-caller-identity aws sts get-caller-identity --profile backup # test one profile on purpose
get-caller-identity requires no IAM permissions at all; it works even when a policy explicitly denies it. So if it fails with InvalidClientTokenId, the problem is the credentials themselves, never your permissions. When it works, it prints the account and the user or role, which tells you whose key you are really using.
- Look at the key prefix in
aws configure listoutput or your credentials file: AKIA or ASIA. That decides whether a session token should be present. - Check where the call goes. If the command works with
--region us-east-1and fails in another Region, skip to the Region section.
Those four checks sort almost every case into one of the sections below.
Cause 1: an environment variable is overriding your profile
This is the cause behind most "but I just replaced the key" stories. The AWS CLI and SDKs look for credentials in a fixed order, and environment variables come before your credentials file. A key you exported for a test months ago, a variable set by an installer, or a CI tool's leftover setting will win over the profile you keep editing. For the AWS CLI v2 the order is roughly: command-line options, then environment variables, then assume-role and web-identity settings, IAM Identity Center, the shared credentials file, the config file, container credentials, and finally the EC2 instance profile.
The three variables to look for are AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN. AWS_PROFILE matters too, because it silently switches profiles.
Windows 11 (PowerShell)
# see every AWS variable in this window
Get-ChildItem Env:AWS*
# remove them from this window
Remove-Item Env:AWS_ACCESS_KEY_ID, Env:AWS_SECRET_ACCESS_KEY, Env:AWS_SESSION_TOKEN -ErrorAction SilentlyContinue
# remove them permanently (they were probably saved with setx)
[Environment]::SetEnvironmentVariable('AWS_ACCESS_KEY_ID', $null, 'User')
[Environment]::SetEnvironmentVariable('AWS_SECRET_ACCESS_KEY', $null, 'User')
[Environment]::SetEnvironmentVariable('AWS_SESSION_TOKEN', $null, 'User')
The permanent ones are the trap on Windows: a variable saved with setx or through System Properties comes back in every new terminal. After removing them, close and reopen the terminal (and VS Code, which caches its environment) before testing again. Check System Properties > Environment Variables for machine-wide entries too; those need an administrator to remove.
macOS and Kali Linux
env | grep ^AWS_ unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN # find where they are set permanently grep -n "AWS_" ~/.bashrc ~/.zshrc ~/.profile ~/.bash_profile 2>/dev/null
Delete the lines you find in those files, open a new terminal, and run aws configure list again. The Type column should now say shared-credentials-file, and aws sts get-caller-identity should return your account.
Ethan's leftover key was in the Windows user variables, saved during a tutorial and forgotten. One SetEnvironmentVariable line and a new terminal later, the backup script ran. "Six months," Jake said. "Six months it was waiting for you," Ethan said.
Cause 2: a session token that is missing, stale or not wanted
Temporary credentials (ASIA keys) only work as a set of three: key ID, secret and session token. Long-term credentials (AKIA keys) only work as a pair. Mixing the two gives InvalidClientTokenId, and the message does not say which way round you got it wrong. These are the shapes that produce the error, with what STS returns for each:
| What was sent | Result | Fix |
|---|---|---|
| AKIA key that does not exist | InvalidClientTokenId, HTTP 403 | Use a current, active key |
| ASIA key without a session token | InvalidClientTokenId, HTTP 403 | Add the session token that came with it |
| ASIA key with the wrong session token | InvalidClientTokenId, HTTP 403 | Get a fresh set from the same source |
| AKIA key with a leftover session token | InvalidClientTokenId, HTTP 403 | Remove aws_session_token / AWS_SESSION_TOKEN |
| Key ID with a trailing space | IncompleteSignature, HTTP 400 (a different error) | Re-paste without spaces |
The fourth row is the one people never suspect. You rotate from temporary credentials to a new long-term key, paste the new key and secret into your credentials file, and leave the old aws_session_token line underneath. AWS sees a long-term key with a token attached and rejects the set. Open the file and look:
# Windows: notepad $env:USERPROFILE\.aws\credentials # macOS / Kali: nano ~/.aws/credentials [default] aws_access_key_id = AKIA................ aws_secret_access_key = ........................................ aws_session_token = IQoJb3JpZ2luX2VjE... <-- delete this line for an AKIA key
For ASIA keys the opposite applies: the token must be there, on one line, complete. Session tokens are several hundred characters long, and copying one out of a web page or a chat message often breaks it across lines or cuts the end off. If you got the set from the AWS access portal, use its "Option 1" or "Option 2" copy buttons, which give you all three values together, or better, configure the profile with aws configure sso so the CLI fetches and refreshes them itself.
Temporary credentials also expire. An expired token usually gives a different error, ExpiredToken: The security token included in the request is expired, which our ExpiredToken guide covers. If you see InvalidClientTokenId with an ASIA key, assume the set is broken or mismatched, not old.
Cause 3: the key was deleted, deactivated, mistyped or belongs to someone else
If the right credentials are being sent and there is no session-token mix-up, check the key itself. Someone with IAM access (you, or an administrator) can see it in the console under IAM > Users > your user > Security credentials > Access keys. Each key shows its status (Active or Inactive), when it was created, and when it was last used. A key that is missing from the list was deleted; one marked Inactive was deactivated, often by a security tool or a rotation script.
The same check from the CLI, run from a working admin profile:
aws iam list-access-keys --user-name backup-script --profile admin aws iam get-access-key-last-used --access-key-id AKIA................ --profile admin
If the key is inactive and should not be, an administrator can reactivate it with aws iam update-access-key --access-key-id AKIA... --status Active --user-name backup-script. If it was deleted, it is gone for good: create a new one with aws iam create-access-key --user-name backup-script and copy both halves straight away, because the secret is shown only once.
Two quieter versions of the same problem:
- A typo you cannot see. A key ID that is one character off is simply an unknown key. Paste it into a plain-text editor and compare it character by character with the console. Watch for a capital O against a zero; access key IDs use only capital letters and the digits 2 to 7.
- A key from another AWS account. If you have several accounts, it is easy to paste the right-looking key from the wrong one. From any working credentials,
aws sts get-access-key-info --access-key-id AKIA...returns the account ID that owns a key, which settles it in one command.
Cause 4: an opt-in Region, or a global-endpoint token used where it is not valid
Some AWS Regions are switched off in every new account until you turn them on. These opt-in Regions include Africa (Cape Town), Asia Pacific (Hong Kong, Hyderabad, Jakarta, Malaysia, Melbourne, Thailand), Canada West (Calgary), Europe (Milan, Spain, Zurich), Israel (Tel Aviv), Mexico (Central), and the Middle East (Bahrain and UAE). Calls to a Region your account has not enabled fail, and with STS the failure shows up as InvalidClientTokenId even though your key is perfectly good. That is the clue: the same command works with --region us-east-1 and fails with --region ap-east-1.
Fix it in this order:
- Enable the Region. In the console, open your account menu (top right) > Account > AWS Regions, find the Region and choose Enable. It can take a few minutes. Enabling the Region automatically activates STS there. If you work across accounts (for example, assuming a role into another account), the Region must be enabled in the account that issues the credentials too.
- Use regional STS endpoints. Credentials obtained from a Region's own STS endpoint work in that Region. Recent CLI and SDK versions already use regional endpoints by default; older ones used the global endpoint,
sts.amazonaws.com. Force regional either way with the environment variableAWS_STS_REGIONAL_ENDPOINTS=regional, or in~/.aws/config:
[profile hk] region = ap-east-1 sts_regional_endpoints = regional
- Or make global-endpoint tokens valid everywhere. Session tokens from the global endpoint come in two versions. Version 1 tokens are valid only in the Regions that are on by default; version 2 tokens work in all Regions, and are longer. An administrator can switch the account to version 2 in IAM > Account settings (the global endpoint setting under Security Token Service), or with the CLI:
aws iam set-security-token-service-preferences --global-endpoint-token-version v2Token # check the current setting aws iam get-account-summary --query "SummaryMap.GlobalEndpointTokenVersion"
Regional endpoints are the better long-term fix: they are faster from where your workload runs and keep working if another Region has a problem. The token-version switch is the quick one when you cannot change every tool's configuration.
One more Region case: for the Regions that are on by default, an administrator can deactivate an individual STS regional endpoint in IAM > Account settings. If your calls fail only against one Region's STS endpoint and that Region is not opt-in, ask whether it was deactivated, and reactivate it there.
AWS China and GovCloud
AWS China (Beijing, Ningxia) and AWS GovCloud (US) are separate partitions with their own accounts and their own keys. A commercial-account key sent to a China endpoint, or the other way round, is an unknown key to that partition and gets InvalidClientTokenId. Check that the Region in your profile matches the partition your key came from.
Lookalike errors and what each one means
Several credential errors look alike at a glance. The code before the colon is what matters:
| Error code | What it means | Where to look |
|---|---|---|
| InvalidClientTokenId | AWS does not accept the access key ID, or the key and token do not belong together | This page |
| UnrecognizedClientException | The same problem as reported by services such as DynamoDB, Kinesis and Lambda ("The security token included in the request is invalid") | This page; the fixes are the same |
| SignatureDoesNotMatch | The key ID is fine; the secret, the signing details or your clock is wrong | SignatureDoesNotMatch guide |
| ExpiredToken | A real session token that has passed its expiry | Refresh the session or SSO login |
| IncompleteSignature | The Authorization header is malformed, often a space or newline pasted into the key | Re-enter the key cleanly |
| Unable to locate credentials | No credentials were found at all; nothing was sent | Unable to locate credentials |
| AccessDenied | AWS knows who you are, but your policies do not allow the action | AccessDenied guide |
A useful way to remember the order: Unable to locate means nothing was sent; InvalidClientTokenId means AWS did not recognize what was sent; SignatureDoesNotMatch means it recognized the key but the signature failed; AccessDenied means it knows exactly who you are and still says no. Each step down is progress.
In boto3 and other SDKs
SDKs follow the same credential order as the CLI, so the same causes apply. The difference is that the error surfaces as an exception in your code. In Python:
import boto3, botocore
session = boto3.Session() # or boto3.Session(profile_name="backup")
creds = session.get_credentials()
print("source:", creds.method) # env, shared-credentials-file, sso, iam-role, ...
print("key ends:", creds.access_key[-4:], "| has token:", bool(creds.token))
try:
print(session.client("sts").get_caller_identity()["Arn"])
except botocore.exceptions.ClientError as e:
print(e.response["Error"]["Code"], "-", e.response["Error"]["Message"])
creds.method answers the "which credentials?" question from inside your program, the same way the Type column does for the CLI. If it prints env when you expected your profile, the environment variables are winning here too. If has token is True for an AKIA key, you have the stale-token problem from Cause 2. For catching these errors cleanly in a larger program, our boto3 ClientError guide shows the pattern.
Hard-coded keys are the other SDK-specific trap. A boto3.client("s3", aws_access_key_id=..., aws_secret_access_key=...) call in the code beats every other source, so rotating the key in your credentials file changes nothing until the code changes too. Search the project for AKIA and aws_access_key_id before you blame anything else.
Terraform, Docker, GitHub Actions and servers
The same error shows up in every tool that talks to AWS. A few places hide credentials especially well:
- Terraform: the AWS provider reads the same environment variables and profiles as the CLI, plus any
access_keyorprofileset in the provider block. Our Terraform credentials guide covers the provider-specific order. - Docker containers: a container sees only the variables you pass with
-eor an env file, and an old.envfile is a classic source of a dead key. Rundocker exec CONTAINER env | grep AWS_to see what the container really has. - GitHub Actions and other CI: a secret pasted with a trailing newline or space breaks the key. Re-create the secret by pasting into a plain-text editor first. Better still, switch the workflow to OIDC with
aws-actions/configure-aws-credentialsand a role, so there is no long-term key to go stale. - EC2 instances: an instance with a role should not need keys at all. If someone also set
AWS_ACCESS_KEY_IDin the instance's environment or user data, those keys override the role, and when they are rotated, everything on the server breaks.
By service and tool: LocalStack, DynamoDB, SQS, Cognito, SES, Bedrock and Go
People search for this error with a service name attached, because it appears wherever AWS credentials are used. The causes above apply everywhere; these are the extra twists each service or tool adds.
LocalStack and DynamoDB Local: your test keys went to real AWS
This is the most common cause in local development, and it looks baffling until you see it. LocalStack and DynamoDB Local accept any made-up credentials, so tutorials tell you to use test / test or fakeMyKeyId. That only works if the request actually goes to the emulator. Forget the endpoint, or set it on one client but not another, and your fake key goes to real AWS, which has never heard of it and answers with InvalidClientTokenId (or, from DynamoDB, UnrecognizedClientException).
# LocalStack listens on 4566, DynamoDB Local on 8000
aws dynamodb list-tables --endpoint-url http://localhost:4566
aws dynamodb list-tables --endpoint-url http://localhost:8000
# or set it once for every service and SDK that supports it
export AWS_ENDPOINT_URL=http://localhost:4566 # PowerShell: $env:AWS_ENDPOINT_URL="http://localhost:4566"
# boto3
boto3.client("dynamodb", endpoint_url="http://localhost:8000", region_name="us-east-1",
aws_access_key_id="test", aws_secret_access_key="test")
If you see this error in a local test suite, check the endpoint before you check anything else. The opposite mistake happens too: AWS_ENDPOINT_URL left set from a LocalStack session sends your real-account commands to an emulator that is not running.
DynamoDB, Kinesis and Lambda: UnrecognizedClientException
These services report rejected credentials with their own code, UnrecognizedClientException, and the same message: "The security token included in the request is invalid." DynamoDB and Kinesis send it with HTTP 400 rather than 403, and Lambda with 403, so a monitoring rule that only watches for 403s will miss the first two. SQS, by contrast, uses InvalidClientTokenId with a 403, like STS. Treat all of them exactly like InvalidClientTokenId: check the credential source, the session token and the Region, in that order.
SQS and the Go SDK: "api error InvalidClientTokenId ... StatusCode: 403"
The AWS SDK for Go v2, and the tools built on it (Terraform, many Kubernetes controllers, CLI tools written in Go), format the error differently, for example operation error SQS: ReceiveMessage, https response error StatusCode: 403, RequestID: ..., api error InvalidClientTokenId: The security token included in the request is invalid. The service name changes (SQS, STS, S3), but the part after api error is the same error, with the same causes. The 403 is the HTTP status, not a separate problem.
Amazon Cognito identity pools
Credentials from a Cognito identity pool are temporary (ASIA keys) and always come with a session token. The classic mistake is passing the access key and secret from GetCredentialsForIdentity to an SDK client but dropping the SessionToken. Pass all three. They also expire, after which you get ExpiredToken and need to fetch a new set.
Amazon SES: "Error sending email: The security token included in the request is invalid"
Apps that send mail through the SES API hit the same credential causes, often in a web host's environment variables that nobody has looked at since setup. One SES-specific trap: SMTP credentials are not API credentials. The SMTP password SES gives you is derived from a secret key and cannot be used as aws_secret_access_key; use SMTP credentials only with the SMTP interface, and real IAM access keys or a role for the API.
Amazon Bedrock
Bedrock calls use the same credential chain as any other service, so a Bedrock script that suddenly fails with this error usually has the same environment-variable or session-token problem. Check the Region as well: Bedrock is available in a specific set of Regions, and if your profile points at an opt-in Region the account has not enabled, STS-based credentials fail there first.
Serverless Framework and other deploy tools
Deploy tools read the same profiles and environment variables. Pass the profile explicitly (for example serverless deploy --aws-profile backup) and run aws configure list --profile backup to confirm what that profile contains, so a stray environment variable cannot win silently.
For IT admins: making this error rare
InvalidClientTokenId is almost always a long-term-key problem, and the lasting fix is to need fewer long-term keys:
- Move people to IAM Identity Center. Users sign in with
aws configure ssoand get temporary credentials that refresh themselves, so there is nothing to paste or rotate. Our Identity Center guide explains the setup. - Give workloads roles, not keys: instance profiles on EC2, task roles on ECS, execution roles on Lambda, OIDC roles for CI.
- When keys must exist, rotate with overlap. Each IAM user can have two access keys. Create the new one, deploy it, confirm
get-access-key-last-usedshows the old one idle, then deactivate (not delete) the old key for a week before deleting it. Deactivation is reversible; deletion is not. - Trace a mystery key.
aws sts get-access-key-info --access-key-id AKIA...tells you which account owns a key you found in a config file or a log. If the key was exposed publicly, follow our leaked access key checklist. - Prefer regional STS endpoints in shared configuration, especially if any team works in an opt-in Region.
Frequently asked questions
What does "The security token included in the request is invalid" mean?
AWS did not accept the access key ID your request was signed with, or the key and its session token do not belong together. The key may be deleted, inactive, mistyped, from another partition, or a temporary key missing its session token.
How do I fix InvalidClientTokenId in the AWS CLI?
Run aws configure list to see which credentials are used and where they come from. Clear stale AWS_ environment variables, remove a leftover aws_session_token for AKIA keys, confirm the key is active in IAM, then test with aws sts get-caller-identity.
Why does aws sts get-caller-identity fail with InvalidClientTokenId?
Because the credentials themselves are rejected. get-caller-identity needs no IAM permissions, so a failure is never a permissions problem; it is the key, the session token, or the Region.
I created a new access key and still get the error. Why?
Usually an environment variable such as AWS_ACCESS_KEY_ID still holds the old key and overrides your credentials file, or an old aws_session_token line is still attached to the new key. Check aws configure list for the source.
Does InvalidClientTokenId mean my secret key is wrong?
Rarely. A valid key ID with a wrong secret gives SignatureDoesNotMatch. InvalidClientTokenId means the key ID itself is not accepted, or the session token does not match it.
What is the difference between AKIA and ASIA keys?
AKIA keys are long-term IAM user keys that work without a session token. ASIA keys are temporary STS keys that only work with their matching session token and expire.
Do I need a session token?
Only for temporary credentials, whose access key ID starts with ASIA. For long-term AKIA keys, remove any session token, because sending one with an AKIA key causes InvalidClientTokenId.
Why does it work in us-east-1 but not in ap-east-1?
ap-east-1 (Hong Kong) is an opt-in Region. Enable it under Account > AWS Regions, and use regional STS endpoints or switch the account's global endpoint tokens to version 2.
What are AWS opt-in Regions?
Regions that are off by default in new accounts, including Cape Town, Hong Kong, Hyderabad, Jakarta, Malaysia, Melbourne, Thailand, Calgary, Milan, Spain, Zurich, Tel Aviv, Mexico Central, Bahrain and UAE. They must be enabled before use.
How do I make STS tokens valid in all Regions?
Use regional STS endpoints, or set the account's global endpoint token version to v2 with aws iam set-security-token-service-preferences --global-endpoint-token-version v2Token. Version 2 tokens are valid in all Regions.
How do I clear AWS environment variables on Windows?
In PowerShell, list them with Get-ChildItem Env:AWS*, remove them for the window with Remove-Item, and remove saved ones with [Environment]::SetEnvironmentVariable('AWS_ACCESS_KEY_ID', $null, 'User'). Then open a new terminal.
How do I check if my access key is active?
In IAM > Users > Security credentials, each access key shows Active or Inactive and when it was last used. From the CLI, an admin can run aws iam list-access-keys --user-name NAME.
How do I find which AWS account an access key belongs to?
Run aws sts get-access-key-info --access-key-id AKIA... from any working credentials. It returns the account ID that owns the key.
Is UnrecognizedClientException the same error?
Yes, in practice. Services such as DynamoDB, Kinesis and Lambda report the same rejected credentials as UnrecognizedClientException with the message "The security token included in the request is invalid." The fixes are the same.
Why do I get InvalidClientTokenId in GitHub Actions?
Most often a secret pasted with a trailing space or newline, a rotated key not updated in the repository secrets, or a session token left set. Switching to OIDC with a role removes long-term keys from CI entirely.
How do I see which credentials boto3 is using?
Call boto3.Session().get_credentials() and print its method attribute, which returns values such as env, shared-credentials-file, sso or iam-role, then test with the STS get_caller_identity call.
Can a wrong system clock cause InvalidClientTokenId?
Clock skew usually shows up as SignatureDoesNotMatch or a "Signature expired" message rather than InvalidClientTokenId. Sync the clock if you see those, but for InvalidClientTokenId check the key and token first.
Why do I get this error with LocalStack or DynamoDB Local?
Your request went to real AWS instead of the emulator, carrying the fake test key. Set --endpoint-url http://localhost:4566 for LocalStack or http://localhost:8000 for DynamoDB Local, or set AWS_ENDPOINT_URL for every client.
What does "api error InvalidClientTokenId" mean?
It is the same InvalidClientTokenId error as printed by the AWS SDK for Go v2 and tools built on it, such as Terraform. The StatusCode: 403 in the message is the HTTP status; the causes and fixes are the same.
Why does Amazon SQS return status code 403 with this message?
SQS is rejecting the credentials exactly as STS does: the key is unknown, inactive, missing its session token, or the Region is not enabled. Check aws configure list and test with aws sts get-caller-identity in the same Region.
Why do Cognito identity pool credentials give this error?
Identity pool credentials are temporary and need their SessionToken. Pass the access key, secret key and session token from GetCredentialsForIdentity together, and fetch a new set when they expire.
Can I use my SES SMTP password as an AWS secret key?
No. The SES SMTP password is derived from a secret key and only works with the SMTP interface. For the SES API, use real IAM access keys or a role.
Can I use AWS China or GovCloud keys with the normal endpoints?
No. China and GovCloud are separate partitions with their own accounts and keys. A key from one partition is unknown in another and returns InvalidClientTokenId.
The backup script has run every night since. Ethan added one line to the shop's setup notes: "Before pasting a new key, run aws configure list." Jake added a second line underneath, in marker: "Check what the computer is reading, not what you typed." It is the most useful thing anyone has written in that notebook.
📌 If you keep one line from this page
InvalidClientTokenId means AWS did not accept the key that was actually sent, so run aws configure list before anything else: a stale environment variable, a leftover session token or an opt-in Region explains most cases.
aws configure list · aws sts get-caller-identity · AKIA = no token, ASIA = token · regional STS endpoints.
Revision note. Written October 17, 2026. "Look before you leap," the proverb says; with AWS keys, look at what is being sent before you make another one.