Skip to content
DevOps AI ToolKit
Newsletter
All guides
AWS with AI By James Joyner IV · · 9 min read

AWS Error Guide: 'Signature expired / InvalidSignatureException' Clock Skew Failures

Fix the AWS 'Signature expired' and InvalidSignatureException clock-skew errors: synchronize host time with NTP and resolve request-time drift.

  • #aws
  • #troubleshooting
  • #errors
  • #signing

Exact Error Message

An error occurred (InvalidSignatureException) when calling the GetCallerIdentity operation: Signature expired: 20260627T140000Z is now earlier than 20260627T141500Z (20260627T143000Z - 15 min.)

A related variant reads:

An error occurred (InvalidSignatureException): Signature not yet current: 20260627T150000Z is still later than 20260627T143000Z (20260627T144500Z + 15 min.)

Both indicate the request timestamp is too far from AWS’s clock. The status code is 403 Forbidden.

What the Error Means

AWS Signature Version 4 includes the request’s timestamp inside the signed payload, so the time at which you signed the request is cryptographically bound to the request itself and cannot be altered in transit. When AWS validates the signature, it compares that embedded timestamp against its own server time and rejects requests that fall outside an allowed window (typically about 5 minutes, with messages showing a 15-minute reference). “Signature expired” means your clock is behind AWS; “not yet current” means your clock is ahead. The credentials and secret key are fine — the local clock has drifted beyond the tolerance the service is willing to accept.

This is purely a time-synchronization problem, not a credentials or permissions issue. The timestamp window exists to limit replay attacks: by refusing requests signed too far in the past or future, AWS narrows the span in which a captured request could be re-sent. That security mechanism is exactly what trips when your host clock drifts, which is why the fix lives entirely in the operating system’s timekeeping and never in your IAM configuration or application code.

Common Causes

  • No NTP synchronization. A VM, container host, or IoT device whose clock was never disciplined drifts steadily over days as the hardware oscillator runs slightly fast or slow, eventually crossing the signing tolerance.
  • VM paused or resumed. A suspended laptop or snapshot-restored VM resumes with a stale clock because no time passed for the guest while wall-clock time advanced outside it.
  • Container without host time sync. Containers inherit the host clock and cannot run their own NTP client; if the host drifts, every container on it drifts in lockstep.
  • Incorrect timezone vs. UTC handling. Rare, but a misconfigured RTC or BIOS clock set to local time instead of UTC can shift request timestamps by whole hours.
  • Network/NTP blocked. Egress to NTP servers (UDP 123) is firewalled, so chrony/ntpd start but can never reach a source to correct the drift they detect.
  • Hardware clock battery dead. On bare metal, a dead CMOS battery resets the clock to a default epoch at every boot, guaranteeing skew until NTP catches up.

How to Reproduce the Error

Skew the system clock forward, then make a signed call (do this only on a disposable host you control):

# Inspect current drift first (read-only)
date -u

On a host whose clock is set several minutes off from real UTC, any signed request fails:

aws sts get-caller-identity
An error occurred (InvalidSignatureException) when calling the GetCallerIdentity operation: Signature expired: ... is now earlier than ...

The numbers in the message are the request time, AWS’s expected window, and AWS’s current time — comparing them tells you the direction and size of the drift.

Diagnostic Commands

Compare your local UTC time against AWS’s server time. AWS returns its time in the HTTP Date header; a simple read-only call plus date reveals the gap:

date -u

Make any AWS call and read the error’s reference timestamp — the third timestamp in parentheses is AWS’s view of “now”:

aws sts get-caller-identity

Check whether the system clock is disciplined by NTP:

timedatectl status

Look for System clock synchronized: yes and NTP service: active. Inspect chrony’s drift if present:

chronyc tracking

The System time and Last offset fields show how far off and in which direction.

Step-by-Step Resolution

  1. Confirm the drift direction. Read the error: “now earlier than” means your clock is behind; “still later than” means it is ahead. The three timestamps in the message let you measure the exact size of the gap, which tells you whether you are dealing with seconds of drift or a clock that is hours wrong.

  2. Check sync status with timedatectl status. If NTP service is inactive, enable it:

    sudo timedatectl set-ntp true
  3. Force an immediate correction with chrony:

    sudo chronyc makestep

    Or with systemd-timesyncd, restart the service to resync.

  4. Unblock NTP egress. If chronyc tracking shows no reachable source, allow outbound UDP 123, or point the host at the AWS Time Sync Service at 169.254.169.123 from inside a VPC, which needs no internet egress and works in fully private subnets.

  5. For containers, fix the host clock; containers cannot run their own NTP daemon and simply read whatever time the host kernel exposes, so correcting one host fixes every container on it at once.

  6. For bare metal, replace a dead CMOS battery and set the hardware clock to UTC so that each reboot starts from the correct reference rather than re-introducing the skew.

  7. Verify with aws sts get-caller-identity — a successful identity response confirms the signature now validates and the embedded timestamp falls within the accepted window.

Prevention and Best Practices

  • Run a disciplined NTP client (chrony or systemd-timesyncd) on every host and confirm System clock synchronized: yes, since an NTP daemon that is installed but never reaches a source provides no protection at all.
  • Inside a VPC, point hosts at the Amazon Time Sync Service (169.254.169.123) so time sync works without internet egress and survives in locked-down private subnets where external NTP is unreachable.
  • Monitor clock offset and alert when drift exceeds a couple of seconds, long before it reaches the signing tolerance, so you correct the host while it is still merely “slightly off” rather than failing.
  • After restoring snapshots or resuming suspended VMs, force a time resync before running workloads, because these are the moments when a clock is most likely to be far out of date.
  • For container fleets, treat host NTP as part of base-image and golden-AMI hardening so every instance launches already disciplined.
  • Keep hardware clocks on UTC to avoid timezone-induced offsets that can shift request timestamps by whole hours at boot.
  • RequestTimeTooSkewed — the S3-specific form of the same clock-skew failure.
  • SignatureDoesNotMatch — the signing computation itself is wrong (bad secret key or canonicalization), not a time problem.
  • ExpiredToken — the temporary session lapsed; unrelated to host clock drift.
  • Signature not yet current — same root cause but the clock is ahead rather than behind.

Frequently Asked Questions

Is this a credentials problem? No. The signature math is correct and the keys are valid; only the embedded timestamp is outside AWS’s allowed window. Fix the clock, not the keys — rotating credentials in response to this error wastes effort and changes nothing.

How much drift is tolerated? Roughly 5 minutes, though the messages reference a 15-minute window. Keep drift to seconds rather than minutes to stay well clear of the edge, since a host already near the limit will fail intermittently as the offset wanders.

Can I fix this in my code instead of the OS? You should fix host time. SDKs sign requests using the system clock, so an unsynced host keeps failing regardless of code changes; there is no application-level workaround that substitutes for a correctly disciplined clock.

Why do all my containers fail at once? They share the host clock and cannot run their own NTP, so one drifted host affects every container on it simultaneously. Fix the host’s NTP and all the containers recover together.

Does the AWS Time Sync Service require internet access? No. 169.254.169.123 is a link-local address reachable from within a VPC without an internet gateway or NAT, which makes it ideal for private subnets that have no outbound path to public NTP servers. More in the AWS guides.

Free download · 368-page PDF

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.