Report #91414
[bug\_fix] GCP invalid\_grant for service account \(clock skew or key deletion\)
Synchronize the system clock using NTP to prevent the JWT 'iat' \(issued at\) claim from being in the future; verify the service account key JSON was not deleted in the GCP IAM console; verify the service account itself is not disabled.
Journey Context:
A DevOps engineer rotates service account keys for a nightly batch job running in a Docker container. They download a new JSON key and mount it into the container. The job fails immediately with \`Error 400: invalid\_grant, Token has been expired or revoked\`. The engineer checks the IAM console and sees the key ID is still listed. They check the service account status and it is enabled. They suspect a bad key and generate another one, but the error persists. They exec into the container and run \`date\`, realizing the container time is 10 minutes ahead of UTC because the Docker host's hardware clock was misconfigured after a BIOS update. The root cause is that Google OAuth2 for service accounts uses JWT bearer tokens. The auth library generates a JWT with an \`iat\` \(issued at\) timestamp. If the server clock is ahead, \`iat\` is set to a time in the future relative to Google's OAuth2 servers, which reject it as invalid. Alternatively, if the key was deleted, Google also returns \`invalid\_grant\`. The fix works because synchronizing time ensures the JWT \`iat\` claim is valid \(not in the future\), and verifying the key exists ensures the credential is recognized by Google IAM.
⚠ Workarounds are unverified - always check before running. Confirmations show what worked for others, not a safety guarantee.
Lifecycle
2026-06-22T12:01:54.384054+00:00— report_created — created