LearnDevOpsHands-On Labs
Troubleshooting Matrix/The security token included in the request is expired
AWSHigh Severity

The security token included in the request is expired

Fix ExpiredToken: run aws sts get-caller-identity, then refresh with aws sso login or assume the role again. Covers stale env vars, session length and CI OIDC.

Observed Error Signature / Log Pattern
An error occurred (ExpiredToken) when calling the ListBuckets operation: The provided token has expired.

Incident Overview

Fix ExpiredToken: run aws sts get-caller-identity, then refresh with aws sso login or assume the role again. Covers stale env vars, session length and CI OIDC.

easy fix·5 min read

By Vishvesh Patel·DevOps Engineer·Updated 21 September 2026

BASHDiagnostic / remediation command
An error occurred (ExpiredToken) when calling the ListBuckets operation: The provided token has expired.

An error occurred (RequestExpired) when calling the DescribeInstances operation: Request has expired.

Error: error configuring S3 Backend: no valid credential sources for S3 Backend found.

ExpiredTokenException: The security token included in the request is expired

Do this first3 steps

Run these in order. Each one tells you what its output means before you change anything.

• Find out which credential source is being used

The Type column says where each value came from: env, shared-credentials-file, or iam-role. Refreshing the wrong source is the most common reason this error persists after a re-login.

• Refresh the session

For SSO this re-authenticates. For a manually assumed role, re-run the assume-role call. get-caller-identity confirms the new credentials work before you retry the real command.

• Clear stale environment variables that override everything else

Environment variables take precedence over profiles and instance roles, so an expired AWS_SESSION_TOKEN exported hours ago silently shadows a perfectly good profile.

Temporary credentials expire. That is the point of them. ExpiredToken means the STS session behind your call has passed its lifetime.

The last three refresh themselves, so if you are seeing this on an instance, something is bypassing the metadata service.

BASHDiagnostic / remediation command
aws configure list

Which source are you actually using?

Type env is the answer in a large share of cases. Environment variables win over everything, so an AWS_SESSION_TOKEN exported this morning shadows the profile you just refreshed, and re-running aws sso login appears to do nothing.

The precedence order, highest first: environment variables, then the CLI's --profile, then AWS_PROFILE, then the default profile, then container credentials, then the instance metadata service.

BASHDiagnostic / remediation command
aws configure list

Refresh it

Confirm before retrying the real thing:

BASHDiagnostic / remediation command
# IAM Identity Center
aws sso login --profile prod

# Manually assumed role
aws sts assume-role \
  --role-arn arn:aws:iam::123456789012:role/deploy \
  --role-session-name deploy-$(date +%s)

Stop assuming roles by hand

Configure the profile to do it, and the SDK refreshes automatically when the session expires:

Now aws --profile deploy s3 ls assumes the role when needed and renews it silently. Exporting the output of assume-role into environment variables is what creates a credential that goes stale in your shell with nothing to refresh it.

BASHDiagnostic / remediation command
# ~/.aws/config
[profile prod]
sso_session = acme
sso_account_id = 123456789012
sso_role_name = Developer
region = eu-west-1

[profile deploy]
source_profile = prod
role_arn = arn:aws:iam::123456789012:role/deploy
duration_seconds = 3600

[sso-session acme]
sso_start_url = https://acme.awsapps.com/start
sso_region = eu-west-1
sso_registration_scopes = sso:account:access

Longer sessions

The default assume-role duration is one hour. Raise the role's maximum, then ask for it:

Note role chaining caps at one hour regardless of the maximum. If you assume role A and then assume role B from A, the second session cannot exceed an hour and duration_seconds above that is rejected. This surprises people building nested assume-role setups for a long deployment.

BASHDiagnostic / remediation command
aws iam update-role --role-name deploy --max-session-duration 14400

RequestExpired is a different thing

This is clock skew, not an expired session. Every signed AWS request carries a timestamp, and the service rejects anything more than five minutes out.

Long-suspended laptops and VMs restored from snapshots are the usual sources. Inside a container, the clock comes from the host, so fix it there.

BASHDiagnostic / remediation command
An error occurred (RequestExpired): Request has expired.

In CI, use OIDC

Static access keys in CI secrets are the thing this error should push you away from. Every major CI platform can exchange an OIDC token for a short-lived AWS role session, with no stored credentials at all:

Credentials are minted per job and expire when it ends. Nothing to rotate, nothing to leak.

BASHDiagnostic / remediation command
# GitHub Actions
permissions:
  id-token: write
  contents: read
steps:
  - uses: aws-actions/configure-aws-credentials@v4
    with:
      role-to-assume: arn:aws:iam::123456789012:role/gha-deploy
      aws-region: eu-west-1

Terraform and the SDK

Terraform reads the same chain. It also caches backend credentials at init time, so a very long apply can outlive the session it started with. For long applies, raise duration_seconds rather than re-running init partway through.

BASHDiagnostic / remediation command
Error: error configuring S3 Backend: no valid credential sources found

A checklist

Frequently Asked Questions

Why does the error persist after I log in again?

Because stale environment variables are overriding your refreshed profile. AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY and AWS_SESSION_TOKEN sit at the top of the credential chain, so an AWS_SESSION_TOKEN exported hours ago shadows whatever aws sso login just wrote. aws configure list shows the source of each value in its Type column. Unset all three and try again; this single step resolves most cases where a re-login appears to have had no effect.

What is the difference between ExpiredToken and RequestExpired?

ExpiredToken means the STS session behind your credentials has passed its lifetime and you need new credentials. RequestExpired means the signed request's timestamp is more than five minutes away from AWS's clock, so it is a time synchronisation problem on your machine rather than a credential one. Check with timedatectl status and restart your NTP service. Laptops resumed from long suspends and VMs restored from snapshots are the usual causes.

How do I get sessions that last longer than an hour?

Raise the role's maximum with aws iam update-role --role-name <name> --max-session-duration 14400, then request it via duration_seconds in the profile or --duration-seconds on the CLI call. The important exception is role chaining: if you assume one role and then assume a second from it, the second session is capped at one hour regardless of the role's maximum, and asking for more is rejected outright. Restructuring to assume the target role directly avoids that cap.

Why do my EC2 instances never hit this?

Because an instance profile's credentials are delivered by the instance metadata service and the SDK refreshes them automatically before they expire. The same is true of ECS task roles and IRSA on EKS. If you do see ExpiredToken on an instance, something is bypassing that mechanism, almost always hardcoded environment variables or a credentials file baked into an AMI. Remove them and let the metadata service supply credentials.

What is the best way to handle AWS credentials in CI?

OIDC federation, which every major CI platform now supports. The platform issues a signed identity token for the job, AWS exchanges it for a short-lived role session, and no long-lived access key is stored anywhere. Credentials are minted per job and expire when it finishes, so there is nothing to rotate and nothing useful to leak. It also gives you per-workflow conditions in the trust policy, so a role can be restricted to one repository and even one branch.

Reference and practice

Learn the underlying concept

Other AWS errors

Free, comprehensive DevOps tutorials and learning roadmaps. Master Docker, Kubernetes, CI/CD, and more.

Get notified about new tutorials and features.

• Roadmaps

• Interview Prep

• Certifications

• Company

© 2026 DevOpsLesson. All rights reserved.

Need to practice this scenario?

Simulate this error condition and practice recovery commands safely in our in-browser terminal.

Open AWS Sandbox