AWS Error Guide: 'SignatureDoesNotMatch' and InvalidSignatureException Auth Failures
Fix AWS SignatureDoesNotMatch and InvalidSignatureException errors: diagnose clock skew, wrong secret keys, region/service mismatch, encoded paths, and proxies.
- #aws
- #troubleshooting
- #errors
- #signature
Overview
Every AWS API request is signed with Signature Version 4 (SigV4): the client builds a canonical request, derives a signing key from the secret access key (scoped to date/region/service), and computes an HMAC. AWS recomputes the same signature server-side and compares. SignatureDoesNotMatch (most services) and InvalidSignatureException (e.g. some service-specific APIs) mean the server’s computed signature did not equal the one you sent. This is an authentication failure, not authorization — the request never gets to permission evaluation.
You see it from the CLI or an SDK:
An error occurred (SignatureDoesNotMatch) when calling the ListObjectsV2 operation: The request signature we calculated does not match the signature you provided. Check your key and signing method.
Or, when the cause is a clock difference:
An error occurred (InvalidSignatureException) when calling the GetCallerIdentity operation: Signature expired: 20260623T120000Z is now earlier than 20260623T121500Z (20260623T121000Z - 5 min.)
It occurs anywhere a request is signed: the CLI, SDKs, presigned URLs, custom signing code, or a proxy that mutates the request after signing.
Symptoms
- API calls fail with
SignatureDoesNotMatchorInvalidSignatureExceptionregardless of IAM policy. - The message mentions
Signature expiredorSignature not yet current(clock skew). - A presigned URL works briefly then returns the error (expiry or path encoding).
- Calls work from one machine but fail from another (bad key or wrong clock).
aws sts get-caller-identity
An error occurred (InvalidSignatureException) when calling the GetCallerIdentity operation: Signature expired: 20260623T120000Z is now earlier than 20260623T121500Z
date -u
Tue Jun 23 12:15:30 UTC 2026
(A 15-minute gap between the request’s timestamp and “now” is a clear clock-skew signature failure.)
Common Root Causes
1. Host clock skew
SigV4 signatures embed a timestamp and are valid only within a ~5-minute window. If the host clock drifts beyond that, every request fails with Signature expired / not yet current.
timedatectl status | grep -E 'System clock|NTP'
System clock synchronized: no
NTP service: inactive
synchronized: no with NTP inactive means the clock can drift out of the window — enable NTP/chrony.
2. Wrong or truncated secret access key
A copy-paste that dropped a character, a trailing space/newline, or the wrong key entirely produces a different signing key and thus a mismatched signature.
aws configure get aws_secret_access_key | wc -c
39
A standard secret access key is 40 characters; wc -c here counts 39 (the trailing newline makes 40 for a correct key, so 39 visible chars is short — re-paste the full key). Verify against the IAM source.
3. Region or service mismatch in the signing scope
SigV4 binds the signing key to a region and service. Signing for the wrong region (e.g. signing us-east-1 for a bucket in eu-west-1) yields a valid-looking but mismatched signature.
aws configure get region
aws s3api get-bucket-location --bucket my-eu-bucket --query LocationConstraint --output text
us-east-1
eu-west-1
The client signs for us-east-1 but the bucket lives in eu-west-1 — set the correct region or use the regional endpoint.
4. A proxy or load balancer mutating the signed request
Anything that rewrites headers, the path, or the body after signing (a corporate proxy adding headers, a gateway re-encoding the path) breaks the canonical request the server reconstructs.
env | grep -iE 'http_proxy|https_proxy'
https_proxy=http://corp-proxy:3128
A proxy in the path is a prime suspect — test a direct connection (or ensure the proxy is signature-transparent).
5. Path/query encoding differences (presigned URLs, special chars)
Keys with spaces, +, or unicode must be encoded identically by signer and server. A double-encoded or under-encoded path in a presigned URL changes the canonical request and fails the signature.
aws s3 presign "s3://my-bucket/reports/Q2 2026.pdf" --expires-in 300
https://my-bucket.s3.amazonaws.com/reports/Q2%202026.pdf?X-Amz-...
If a downstream tool re-encodes %20 to + (or vice versa), the signature breaks — keep the presigned URL byte-for-byte.
6. Session token missing or mismatched (temporary credentials)
Temporary credentials (from STS/assume-role) require the X-Amz-Security-Token. Using the access key + secret without the session token (or with a stale token) fails the signature/credential check.
aws configure get aws_session_token | wc -c
1
A length of 1 (empty + newline) on credentials that are temporary means the session token is missing — supply the full STS triple.
Diagnostic Workflow
Step 1: Read which variant and clause you got
aws sts get-caller-identity 2>&1
Signature expired / not yet current points at the clock; a bare “request signature we calculated does not match” points at the key, scope, or request mutation.
Step 2: Check the clock first (cheapest fix)
date -u; timedatectl status 2>/dev/null | grep -E 'synchronized|NTP'
If the clock is off by more than a couple of minutes, fix NTP before anything else — it explains most intermittent signature failures.
Step 3: Verify the credentials in use
aws configure list
aws configure get aws_secret_access_key | wc -c
Confirm the right profile is active, the secret is full length, and (for temporary creds) a session token is present.
Step 4: Confirm region/endpoint match the resource
aws configure get region
aws s3api get-bucket-location --bucket <BUCKET> --query LocationConstraint --output text
Sign and call against the resource’s actual region; cross-region S3 calls must use the regional endpoint.
Step 5: Eliminate proxies and re-test directly
https_proxy= http_proxy= aws sts get-caller-identity
If the call succeeds with proxies unset, a proxy is mutating the signed request — make it signature-transparent or bypass it for AWS.
Example Root Cause Analysis
A batch job on a long-lived EC2 instance began failing every API call with InvalidSignatureException: Signature expired after running fine for weeks. IAM had not changed, so the team suspected credentials — but the message named the clock.
Checking the host time:
date -u; timedatectl status | grep -E 'synchronized|NTP'
Tue Jun 23 11:48:55 UTC 2026
System clock synchronized: no
NTP service: inactive
The instance clock had drifted to ~12 minutes behind real time, well outside SigV4’s 5-minute window. The chrony service had stopped after a package update and was not restarted, so the clock drifted unbounded.
Fix: re-enable and start time sync, then verify the drift is gone.
sudo systemctl enable --now chronyd
chronyc tracking | grep -E 'System time|Leap'
System time : 0.000042 seconds slow of NTP time
With the clock back inside the window, aws sts get-caller-identity succeeded immediately — no credential change was needed.
Prevention Best Practices
- Run NTP/chrony on every host that calls AWS and alert when
synchronized: no; clock skew is the single most common SigV4 failure and is fully preventable. - Use SDK-managed signing (CLI, SDKs, IAM roles) rather than hand-rolled SigV4 code; let the SDK handle canonicalization, scope, and encoding.
- Prefer instance profiles / IRSA / role assumption over long-lived keys so credentials rotate automatically and always carry a valid session token.
- Keep presigned URLs byte-for-byte and short-lived; never let downstream tooling re-encode the path or query.
- Make any proxy in the request path signature-transparent (no header/path/body rewrites), or bypass it for AWS endpoints.
- For sorting a clock-skew failure from a credential or scope mismatch in logs, the free incident assistant can read the message clause and point you to the likely cause. More walkthroughs are in the AWS guides.
Quick Command Reference
# Read the exact failure clause
aws sts get-caller-identity 2>&1
# Check the clock (top suspect)
date -u; timedatectl status 2>/dev/null | grep -E 'synchronized|NTP'
# Verify credentials in use
aws configure list
aws configure get aws_secret_access_key | wc -c
aws configure get aws_session_token | wc -c
# Confirm region/endpoint vs. the resource
aws configure get region
aws s3api get-bucket-location --bucket <BUCKET> --query LocationConstraint --output text
# Test without proxies
https_proxy= http_proxy= aws sts get-caller-identity
Conclusion
SignatureDoesNotMatch / InvalidSignatureException means the server-computed SigV4 signature did not match the one you sent — an authentication, not authorization, failure. The usual root causes:
- Host clock skew outside the ~5-minute SigV4 window.
- A wrong or truncated secret access key.
- A region or service mismatch in the signing scope.
- A proxy or load balancer mutating the request after signing.
- Path/query encoding differences (presigned URLs, special characters).
- A missing or stale session token on temporary credentials.
Read the message clause first — Signature expired is the clock; “does not match” is the key, scope, or a mutated request — and check the clock before touching credentials.
Download the Free 500-Prompt DevOps AI Toolkit
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.