---
cuppy_hub: aws
cuppy_path: reference/sts/errors.md
cuppy_section: docs
cuppy_doc: 9H6Q-WAPM
cuppy_doc_uuid: d9d9b24b-b0f8-4c42-bf30-972d7ba77444
cuppy_permalink: https://cuppy.io/aws/d/9H6Q-WAPM
cuppy_version: 4
cuppy_updated: 2026-10-23T16:16:52.575Z
cuppy_canonical: https://cuppy.io/aws/docs/reference/sts/errors
cuppy_mcp: https://cuppy.io/mcp
cuppy_body_sha256: 587715f4abf10adc0bb7ac695f236765dabcbd11c6d0be558237653f0f8f0927
# cuppy_body_sha256 is over the document body ALONE, excluding both generated blocks.
---


# STS and credential errors

**First, find out which identity is actually calling and where its credentials came from:**

```
aws sts get-caller-identity --debug
```

The debug output names the credential source (environment variables, a profile in `~/.aws/credentials` or `~/.aws/config`, SSO, a role). Most errors on this page are the wrong or stale credentials being picked up first. Policy denials (`is not authorized to perform`) are a different problem: see `reference/iam/errors.md`.

---

## `ExpiredToken` — `The security token included in the request is expired`

**Means:** the temporary credentials used to sign this request have passed their expiry.

**Causes, most likely first:**
1. **The session simply ran out.** Credentials from AssumeRole last one hour unless a longer `DurationSeconds` was requested, and cannot be renewed in place. Check: when the credentials were issued.
2. **Stale values in environment variables.** `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY` and `AWS_SESSION_TOKEN` are not refreshed by anything, and environment variables win over profiles. Check: `printenv | grep AWS` (Linux, macOS) or `set AWS` (Windows).
3. **Stale cached credentials in the CLI cache.** Check: the contents of `~/.aws/cli/cache`.
4. **The profile you meant is not the one in use.** Check: `aws configure list --profile <name>`.
5. **The machine clock is wrong.** A request that reaches AWS more than five minutes away from its own timestamp is rejected. Check: compare the system time with a reliable source.

**Fix:**
- Unset stale credential environment variables.
- Clear the CLI cache: `rm -r ~/.aws/cli/cache` (Linux, macOS) or `del /s /q %UserProfile%\.aws\cli\cache` (Windows).
- Prefer a profile with `role_arn` and `source_profile`, so the CLI fetches fresh role credentials itself, instead of pasting credentials into files.
- If sessions end too early for a long job, request a longer session with `DurationSeconds`, up to the role's maximum session duration. Role chaining caps the session at one hour regardless.
- Correct the system clock.
- Confirm with `aws sts get-caller-identity`.

## `ExpiredToken` returned by AssumeRoleWithWebIdentity

**Means:** a different problem with the same code. The STS API reference defines `ExpiredToken` (HTTP 400) as the *web identity token you passed in* being expired or invalid, not your own AWS credentials. You hit this in web-identity federation such as CI pipelines using OIDC (for example GitHub Actions).

**Fix:** obtain a new identity token from the identity provider and retry. Do not clear AWS credential caches; they are not involved.

## `The provided token has expired`

**Means:** the login token behind an IAM Identity Center (SSO) or `aws login` profile has expired, so the CLI or SDK cannot fetch new short-term credentials.

**Fix:** sign in again: `aws sso login --profile <name>` for an Identity Center profile, or `aws login` for a console-credentials profile. With `aws login`, short-term credentials last 15 minutes and are refreshed automatically for up to 12 hours; after that a new login is required.

## `InvalidClientTokenId` — `The security token included in the request is invalid`

**Means:** AWS does not recognise the access key ID used to sign the request.

**Causes, most likely first:**
1. **The access key was deleted, deactivated or never existed.** Check: in the account, look up the access key ID the debug output shows.
2. **The credentials came from somewhere unexpected.** The provider chain stops at the first source it finds, so an old key in an environment variable or the default profile shadows the one you meant. Check: `aws sts get-caller-identity --debug` and read the source.
3. **The key pair is mismatched or mistyped**, for example a session token from one session with keys from another. Check: `aws_access_key_id`, `aws_secret_access_key` and `aws_session_token` in the profile all come from the same issuance.
4. **The request went to a Region the account has not enabled** (field reports; UNVERIFIED in official sources). Check: whether the target Region is an opt-in Region.

**Fix:** remove the stale source (unset environment variables, correct the profile), replace deleted keys, and prefer temporary credentials over long-term keys. Confirm with `aws sts get-caller-identity --debug`.

## `MalformedPolicyDocument` (from AssumeRole)

**Means:** the session policy passed in `Policy` is not valid JSON policy, or contains characters outside the allowed range. HTTP 400; the message says what is wrong.

**Fix:** validate the JSON and the policy grammar. Session policy text may contain only tab, line feed, carriage return and characters from space through `ÿ`.

## `PackedPolicyTooLarge`

**Means:** the session token would exceed its maximum size. Session policies and session tags both add to the token. HTTP 400. This can happen even when each individual limit is met: inline plus managed session policies within 2,048 characters, at most 10 managed policy ARNs, at most 50 session tags.

**Fix:** pass fewer or shorter session tags and session policies. Watch `SessionTokenUtilization` in the AssumeRole response (percentage of the maximum used); `PackedPolicySize` is deprecated.

## `RegionDisabled`

**Means:** STS is not activated in the requested Region for the account that would issue the credentials. HTTP 403.

**Fix:** an administrator of that account activates STS for the Region in the IAM console, or the caller uses an STS endpoint in a Region where it is active.

## Failures without a verified message string

These are documented failure conditions whose exact error text was not found in an official source. Search the hub with the text you hold; if you hold one of these, record the verbatim message in a drift report so this entry can be indexed.

- **`DurationSeconds` above the role's maximum session duration.** The call fails. Valid range is 900 to 43200 seconds, capped by the role's own setting.
- **Role chaining with `DurationSeconds` above one hour.** The call fails; a chained session cannot exceed one hour.
- **Missing or expired MFA `TokenCode`** when the trust policy requires MFA. AssumeRole returns an access denied error; see the trust-policy entry in `reference/iam/errors.md`.

## When none of these fits

Run `aws sts get-caller-identity` with the same credentials to confirm who you are. Read the role's trust policy (`aws iam get-role --role-name <r> --query Role.AssumeRolePolicyDocument`) against the caller's ARN, the external ID and the session tags. Then find the failed `AssumeRole*` event in CloudTrail (in the caller's account and Region) and read its `errorMessage` (`guides/iam/fix-access-denied.md`).


---
<!-- cuppy -->
You are reading one file. The same content is free over MCP at https://cuppy.io/mcp with no signup: ranked search across all 131 documents in this hub, the merged view when you work in a layer, known workarounds matched to the error you hit, and depth control so you spend tokens on what you need. Start with the `_hello` tool. How to connect: https://cuppy.io/aws/ Something wrong in this document? Report it with the `session feedback` tool on the same endpoint.
<!-- /cuppy -->
