InvalidClientTokenId occurs when Terraform cannot authenticate with AWS because the provided security credentials are invalid, expired, or misconfigured. This typically happens due to incorrect access keys, special characters in secrets, or expired temporary credentials.
InvalidClientTokenId is an AWS authentication error (HTTP 403) thrown when Terraform's AWS provider receives a security token or set of credentials that AWS does not recognize or trust. This differs from generic 'permission denied' errors—the issue isn't that the credentials lack permission, but that AWS has rejected the credentials themselves as invalid. The error surfaces because Terraform attempts to call AWS APIs to plan or apply infrastructure changes, and AWS rejects the request at the authentication stage before even checking permissions. Common triggers include malformed credentials, special characters that weren't properly escaped, expired temporary tokens, or environment variable conflicts where Terraform reads the wrong credentials.
Test your AWS credentials independently to confirm they're valid before troubleshooting Terraform:
# Verify current credentials are recognized by AWS
aws sts get-caller-identity
# Output should show your Account, UserId, and Arn:
# {
# "UserId": "AIDAI...",
# "Account": "123456789012",
# "Arn": "arn:aws:iam::123456789012:user/username"
# }If this command fails with InvalidClientTokenId, the issue is with your credentials themselves, not Terraform. If it succeeds, the issue is Terraform-specific configuration.
Inspect what Terraform is actually reading for credentials:
# Print current environment variables (be careful—this shows your secret!)
echo $AWS_ACCESS_KEY_ID
echo $AWS_SECRET_ACCESS_KEY
echo $AWS_SESSION_TOKEN
# Or use env to filter for AWS variables
env | grep AWSVerify:
1. Access Key ID starts with AKIA or ASIA
2. Secret Access Key contains only alphanumeric characters plus + and /
3. No extra spaces or line breaks
4. Session token (if present) is not expired
If credentials look wrong, clear them and reconfigure:
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
# Reconfigure from AWS credentials file or IAM consoleAWS CLI caches credentials locally, which can become stale. Clear the cache and regenerate temporary credentials:
# Remove AWS CLI cache
rm -rf ~/.aws/cli/cache/*
# If using temporary credentials with MFA, log in again
aws sts get-session-token --serial-number arn:aws:iam::123456789012:mfa/username --token-code 123456
# Or use a credential refresher like saml2aws
saml2aws login
# Verify the new credentials work
aws sts get-caller-identityThen retry Terraform:
terraform planThis is the fastest fix for InvalidClientTokenId related to expired or stale temporary credentials.
If credentials are old or you suspect they've been compromised, regenerate them in the AWS IAM console:
1. Go to AWS Console > IAM > Users > Your Username
2. Under 'Security credentials', delete old Access Keys
3. Create a new Access Key
4. Copy the Access Key ID and Secret Access Key immediately (you can't retrieve them later)
5. Update your credentials:
# Option A: Update ~/.aws/credentials file
# Edit ~/.aws/credentials and replace Access Key ID and Secret Access Key
vi ~/.aws/credentials
# Option B: Use aws configure
aws configure
# Enter new Access Key ID and Secret Access Key when prompted
# Option C: Set environment variables
export AWS_ACCESS_KEY_ID="AKIA..."
export AWS_SECRET_ACCESS_KEY="wJalr..."
# Verify
aws sts get-caller-identity
terraform planIMPORTANT: Delete the old access key immediately after creating the new one to prevent security issues.
If you're providing AWS credentials in multiple places, Terraform might be reading the wrong one. Terraform checks credentials in this order: (1) Provider block variables, (2) Environment variables, (3) Shared credentials file
Simplify by using only one method:
# OPTION 1: Remove hardcoded credentials from provider block
provider "aws" {
region = "us-east-1"
# Remove: access_key = "..."
# Remove: secret_key = "..."
}
# OPTION 2: Or if using provider block, don't set environment variables
provider "aws" {
region = "us-east-1"
access_key = var.aws_access_key
secret_key = var.aws_secret_key
}Then ensure consistency:
# Clear all AWS environment variables
unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY
unset AWS_SESSION_TOKEN
unset AWS_PROFILE
# Use only your configured method
terraform planOutdated AWS provider versions may have authentication bugs. Update to the latest stable version:
# In your main.tf or versions.tf
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0" # Use latest major version
}
}
}Then update:
terraform init -upgrade
terraform planCheck the Terraform AWS provider changelog on GitHub for any authentication-related fixes in recent versions. You can also check what version you're currently using:
terraform versionSpecial characters in AWS secrets are a leading cause of InvalidClientTokenId (40% of reported cases). AWS secret access keys contain 40 random alphanumeric characters plus + and / symbols. These characters sometimes fail to encode correctly when: (1) copied from AWS console and pasted into environment variables without proper escaping, (2) stored in configuration management systems that don't preserve special characters, or (3) used in scripting contexts where shell interpretation removes or modifies the characters. Solution: When setting secrets in environment variables, always wrap in single quotes to prevent shell interpretation. For CI/CD pipelines (GitHub Actions, GitLab CI), use the platform's secrets management feature rather than hardcoding or pasting raw credentials.
For AWS China (cn-*) or AWS GovCloud (us-gov-*) regions, credentials from standard AWS partitions won't work. You must use credentials scoped to the specific partition. Region configuration also matters: some regions like me-south-1 and ap-east-1 must be explicitly enabled in your AWS account before use.
For assume-role scenarios where Terraform uses STS to assume a cross-account role, InvalidClientTokenId can indicate the role ARN is incorrect, the source credentials lack permission to assume the role, or trust relationships aren't properly configured. Enable debug logging with TF_LOG=DEBUG to see exactly which credentials Terraform is attempting to use.
Error: Error rendering template: template not found
How to fix "template not found" error in Terraform
Error: Error generating private key
How to fix 'Error generating private key' in Terraform
Error creating Kubernetes Service: field is immutable
How to fix "field is immutable" errors in Terraform
Error: Error creating local file: open: permission denied
How to fix "Error creating local file: permission denied" in Terraform
Error: line endings have changed from CRLF to LF
Line endings have changed from CRLF to LF in Terraform