Skip to main content
DevOps Insightsguides & answers

AWS · troubleshooting

ExpiredToken: The security token included in the request is expired

Temporary AWS credentials have a lifetime, from 15 minutes to 12 hours, and the ones being used have run out. Most often they were exported as environment variables, which never renew and override your profile. Unset them and let a profile, SSO or the role refresh credentials for you.

First published

New to this? Read what is actually happening first, then come back to the steps.

On this page · 10 sections

Before you start

  • The failing command or program, run in the same shell or environment.
  • The AWS CLI, for aws configure list and aws sts get-caller-identity.

Run this first

step 1 of 2
aws configure list

Look for access_key with TYPE env means exported variables are in charge

Shows where the credentials in use come from, without calling AWS.

Work out which cause you have

A few questions to narrow the list. Every answer ends in a command that confirms or rules the cause out — this cannot see your cluster, so nothing here is a certainty until you have checked.

Narrow it down

0 answered · nothing is sent anywhere

Is AWS_SESSION_TOKEN set in the environment that fails?

Cause space

3 of 3 still possible

  • Old credentials exported as environment variablesCommon
  • The job runs longer than the session allowsCommon
  • The IAM Identity Center sign-in has endedOccasional

Nothing ruled out yet. Answer the question above and the branches your answer eliminates will strike through here.

Check it with a tool

Or diagnose it manually

In this order. The first command usually contains the whole answer.

  1. Step 1

    aws configure list

    Shows where the credentials in use come from, without calling AWS.

    Look for access_key with TYPE env means exported variables are in charge

  2. Step 2

    aws sts get-caller-identity

    The cheapest call that uses the credentials; it fails with the same error if they have expired.

    Look for Your account and role, or the ExpiredToken error

Every cause, and how to fix it

Ordered by how often each one turns out to be the answer.

Old credentials exported as environment variables

Common

Keys were exported earlier, copied from a console, printed by a script or by aws configure export-credentials. They override every profile and never renew.

Confirm

env | grep -E '^AWS_(ACCESS_KEY_ID|SECRET_ACCESS_KEY|SESSION_TOKEN)=' | sed 's/=.*/=…/'
aws configure list

AWS_SESSION_TOKEN set, and aws configure list showing access_key from env

Fix

  • Unset them in that shell, so the profile is used again: unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN.
  • Use a named profile instead (role_arn plus source_profile, or IAM Identity Center), so the SDK renews credentials itself.
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN

Then aws sts get-caller-identity --profile NAME should work again.

The job runs longer than the session allows

Common

A long Terraform apply, a database restore or a batch job outlives the role's session, often one hour because of role chaining or the role's default maximum.

Confirm

aws iam get-role --role-name ROLE --query 'Role.MaxSessionDuration'

3600 (one hour), or a value shorter than the job takes

Fix

  • Raise the role's maximum session duration (up to 12 hours) and request a longer DurationSeconds, if the job really needs it and is not role chaining.
  • Avoid chaining: assume the target role directly from your user or SSO session, since chained sessions are capped at one hour.
  • Run long jobs where credentials renew themselves: on EC2, ECS or EKS with a role, or with a profile the SDK can refresh.

The IAM Identity Center sign-in has ended

Occasional

SSO-issued role credentials are renewed only while your Identity Center session is valid. When that ends, tools holding the last credentials eventually fail.

Confirm

aws sts get-caller-identity --profile NAME

An SSO token error, or the expired-token error, for an SSO profile

Fix

  • Sign in again: aws sso login --profile NAME, then retry.

Understanding it properly

Skip this if you are mid-incident — the working part of the page is above. Worth reading afterwards, because understanding the mechanism is what stops the next one.

In plain terms

Many AWS credentials are temporary: when you assume a role, sign in through SSO or use MFA, AWS hands out keys that stop working after a set time. Tools that get those keys from a profile ask for fresh ones automatically. Keys you copied into environment variables do not: they keep being used, take priority over everything else, and fail the moment they expire.

Words used on this page

Temporary credentials
An access key, secret and session token issued by AWS STS for a limited time.
Session duration
How long assumed-role credentials last: 15 minutes up to the role's maximum, which can be set from 1 to 12 hours.
Role chaining
Assuming a role using credentials from another role. Its sessions are limited to one hour.
AWS_SESSION_TOKEN
The environment variable holding a temporary credential's token. Exported values are fixed and are not renewed by the SDK.
What is actually happening

AWS STS issues temporary credentials with a fixed lifetime. For AssumeRole, DurationSeconds ranges from 900 seconds up to the role's maximum session duration, which an administrator sets between 1 and 12 hours. Using one role to assume another (role chaining) is limited to one hour.

The SDK and CLI print An error occurred (ExpiredToken) when calling the OPERATION operation: The security token included in the request is expired. Some services return ExpiredTokenException with the same meaning: request a new token.

Credentials in environment variables (AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_SESSION_TOKEN) take precedence over the config files, and botocore reads them as fixed credentials for the life of the process. So after you log in again, an old exported token still wins and still fails.

Credentials from a profile with role_arn and source_profile, from IAM Identity Center or from an instance or container role are fetched by the SDK, which requests new ones as they expire. A long-running job that read its credentials once at start does not get that.

How to tell this is your problem
WhereWhat you see
AWS CLI or boto3An error occurred (ExpiredToken) when calling the GetCallerIdentity operation: The security token included in the request is expired
Terraform, Go SDKapi error ExpiredToken: The security token included in the request is expired
TimingWorks for an hour (or the role's limit) after you set the credentials, then fails

How to know it is actually fixed

  • aws sts get-caller-identity returns the expected role.
  • The long-running job completes, or runs past the old one-hour point.

Stopping it happening again

  • Do not export temporary credentials into long-lived shells, CI variables or .env files; reference a profile instead.
  • Size role session durations for the jobs that use them, and avoid role chaining for long work.
  • In CI, use the platform's OIDC role assumption so every job gets fresh credentials.

Security considerations

  • Do not fix this by switching to long-lived access keys. Temporary credentials expiring is the safety feature; let the tooling refresh them.
  • Do not paste session tokens into chat, tickets or scripts committed to Git; they are valid credentials until they expire.

Sources

Behaviour described here is drawn from official documentation. Where a figure could not be confirmed on an official page it is attributed in the text rather than stated as canonical.

Did this get you to an answer?

No text box on purpose — please do not paste production logs anywhere

Something wrong or out of date? Report it