You have six digits in front of you, the service says they are invalid, and you would rather be inside the account than reading about it. Work down this page in order. The first section takes about a minute and ends most of these, whichever app the code came from — Google Authenticator, Microsoft Authenticator, Authy or any other.
The order matters because nearly every page on this question stops in the same place. Google's own troubleshooting for Authenticator is four lines long, and the last one is "The time on your device is synced and correct for your local time zone" (Google). That advice is correct, and it is also where the available help runs out. Everything after the first section here is the set of causes that survive a correct clock — which is exactly where you are standing if automatic time is already on and the code is still being refused.
Authenticator code invalid: the four checks that take a minute
- Use a fresh code. If the one on screen has only a few seconds left, do not send it. Wait for the next one and type it immediately. GitHub's own instruction is literally this: "Codes change every 30 seconds. Open your TOTP app, wait for the next code to appear and enter it immediately" (GitHub docs).
- Check you are reading the right entry. Not the right logo — the right account line underneath it. If you have two accounts at one provider, the issuer is identical on both.
- Type the digits yourself. Paste and autofill can carry a trailing space or a stray character into a field that will not forgive one. Six digits, nothing else.
- Turn on automatic date and time on the device generating the code, then generate a new one.
If one of those did it, stop reading and go and finish what you were doing. If automatic time has been on the whole time and the code is still rejected, the rest of this page is the part nobody writes.
Time sync: how much slack a 2FA code actually gets
Worth knowing precisely, because "set your clock" is useless advice without a sense of scale.
A TOTP code is a function of the shared secret and the current time, chopped into steps. RFC 6238 sets the default: "X represents the time step in seconds (default value X = 30 seconds)" (RFC 6238 §4.1). Both sides compute the same number from the same step without ever talking to each other, which is why the code works on a plane and why a wrong clock breaks it.
The slack is a policy the verifier sets, and the standard is cautious about it. On transmission delay: "A larger acceptable delay window would expose a larger window for attacks. We RECOMMEND that at most one time step is allowed as the network delay" (RFC 6238 §5.2). On drift: "If the time step is 30 seconds as recommended, and the validator is set to only accept two time steps backward, then the maximum elapsed time drift would be around 89 seconds, i.e., 29 seconds in the calculated time step and 60 seconds for two backward time steps" (RFC 6238 §6).
So: a few seconds out is fine almost everywhere. A minute out fails almost everywhere. And there is no middle ground you can negotiate — a clock that is 90 seconds slow produces codes that are arithmetically correct and universally rejected.
Where to set it:
- iPhone and iPad — Settings, General, Date & Time, Set Automatically. If it is already on, toggle it off and on again to force a fresh fetch.
- Android — Settings, System, Date & time, Set time automatically, plus the network-provided time zone.
- Windows — Settings, Time & language, Date & time, Set time automatically, then Sync now.
- macOS — System Settings, General, Date & Time, Set time and date automatically.
Time correction for codes is gone from Google Authenticator
Plenty of pages still tell Android users to open Google Authenticator, go to Settings, tap Time correction for codes, and choose Sync now. That menu is gone. Google's own Authenticator page now carries the correction in bold at the top: "Important: The time correction setting is no longer available in version 7.0. The app now uses the time setting on your operating system" (Google).
That is worth generalising rather than filing as trivia. Your authenticator app reads the device clock; it does not own one. The clock is an operating-system setting, so it is the operating system you fix — in every app, including this one.
Why is my authenticator code wrong when the time is right?
Before working through them, one diagnostic that costs ten seconds and halves the list: try a second account in a different service.
- Codes rejected everywhere — it is the device, its clock, or the whole vault.
- Exactly one service rejecting — it is that entry or that verifier, and causes 1, 2, 5 and 6 below are where to look.
1. Authenticator code invalid after a new phone or a second enrolment
None of the pages that stop at "turn on automatic date and time" reach this one, and it is the first thing to check once the clock is ruled out.
The QR code you scan carries the secret. Set 2FA up a second time — new phone, reinstalled app, disabled and re-enabled it in a panic last year — and the service issues a different secret and stops honouring the old one. Cloudflare states the consequence plainly: "When you reconfigure your mobile application authentication, your previous TOTP codes are invalid", and, importantly, "Reconfiguring TOTP mobile application authentication does not turn off 2FA" (Cloudflare docs).
The trap is what the retired entry does next: nothing visible. It keeps counting down, keeps producing six well-formed digits, and nothing in your authenticator knows or can know that the other side stopped listening. You are reading a real code for a secret that was retired.
What to do:
- Search your authenticator for the service name and see how many entries come back. Two is the answer you are hoping for, because it explains everything.
- Try the other one. If it works, you have found it.
- Delete the dead entry — but only after you have signed in with the live one, which is GitHub's standing advice for the same reason: "Only replace the existing 2FA method on your device (e.g. the GitHub entry in your TOTP app) after your new method is saved to your GitHub account completely" (GitHub docs).
If both entries are rejected, the secret you still hold is not the one the service holds, and that is a recovery problem rather than a code problem. Jump to the last section.
2. Two accounts at one provider, and you are copying the wrong code
Different cause, same symptom, and it is the one the standard explicitly only half-solves.
The otpauth:// URI behind every QR has a label made of an account name "optionally prefixed by an issuer string identifying the provider or service managing that account". The spec says why: "This issuer prefix can be used to prevent collisions between different accounts with different providers that might be identified using the same account name, e.g. the user's email address" (Key Uri Format).
Read that carefully. The issuer prefix separates accounts at different providers. It does nothing at all for two accounts at the same provider — a personal and a work login, two AWS roles, an admin account and a daily driver. Those arrive in your app with an identical issuer, an identical generated avatar, and an account line you have to actually read. GitHub puts the outcome in one sentence: "Codes generated for a different account will not work."
Fix it once rather than every time: rename both entries so the difference is in the first few characters, where your eye lands, not at the end of a truncated email address.
3. The code expired between reading it and submitting it
A 30-second step is not 30 seconds of usable time. Reading the digits, typing them, and the round trip to the server all come out of the same budget, and the verifier checks the step at the moment it receives the request, not the moment you started typing.
AWS makes the cost of this unusually visible in its MFA resync flow, which asks for two consecutive codes and warns: "Submit your request immediately after generating the codes. If you generate the codes and then wait too long to submit the request, the request appears to work but the device remains out of sync" (AWS docs).
The rule is simple: if the ring is nearly empty, wait. A code with four seconds left is a code you are about to waste, and on a service that also counts failed attempts, wasting them has a second cost.
4. The service accepts a narrower time window than you assume
Nothing in the TOTP standard fixes how generous a verifier has to be. It is a dial each service sets, and the range in practice is wide enough to explain why one service accepts a code that another has just refused.
Two documented ends of that range:
- Keycloak ships a look-around window of one interval: "The number of intervals the server attempts to match the hash... The default value of 1 is adequate" (Red Hat build of Keycloak). With the default 30-second period that is the current step plus one either side — roughly a 90-second span in total.
- Okta Verify sits an order of magnitude further out: codes are generated every 30 seconds but have "a TTL of 300 Seconds", described as "a hard-coded value that may not be modified", with a separate configurable Clock Drift Interval for custom TOTP (Okta).
Bybit's help page on this exact error warns that a time difference of only a few seconds can be enough to fail — which, on a tight verifier, is honest.
What follows from this is the thing worth internalising: you cannot widen someone else's window, and neither can your authenticator app. Any app that claims to make codes "more tolerant" is either adjusting its own clock or misdescribing itself. The only lever on your side of the wire is to be accurate and fast.
5. A setup key typed in by hand instead of scanned
If the entry was added with "enter a setup key" rather than by scanning, there are two independent ways it is quietly wrong.
The character set. Secrets are base32, and the base32 alphabet is A–Z and 2–7 only. There is no zero, no one, no eight and no nine in it. RFC 4648 explains why, and also what happens when someone types one anyway: "The characters '0' and 'O' are easily confused, as are '1', 'l', and 'I'. In the base32 alphabet below, where 0 (zero) and 1 (one) are not present, a decoder may interpret 0 as O, and 1 as I or L" (RFC 4648 §6). So a mistyped character does not reliably produce an error. It may be silently guessed into a different byte, and a different byte is a different secret — which generates perfectly formatted six-digit codes that will never once be accepted. The same goes for a transposed pair, a dropped character, and trailing = padding, which the Key Uri Format says "is not required and should be omitted".
The parameters. A QR can specify SHA-256 or SHA-512, seven or eight digits, and a period that is not 30. Type the secret by hand into a form that assumes SHA-1, six digits and 30 seconds, and the entry is wrong in a way that looks completely normal. This is the classic one-service-fails case from the diagnostic above.
Either way the fix is the same, and retyping is not it: get a fresh QR from the service — turn 2FA off and on again there if you have to, while you can still sign in — and scan it.
6. HOTP: the counter has walked away from the server
If the entry has a button you press to get the next code rather than a countdown ring, it is HOTP, and the failure mode is completely different.
The asymmetry is designed in: "Although the server's counter value is only incremented after a successful HOTP authentication, the counter on the token is incremented every time a new HOTP is requested by the user. Because of this, the counter values on the server and on the token might be out of synchronization" (RFC 4226 §7.4). Every code you generate and do not use pushes your side one step further ahead of theirs.
Servers absorb some of that: "We RECOMMEND setting a look-ahead parameter s on the server, which defines the size of the look-ahead window." But s is finite and often small — Keycloak's HOTP default is the same look-around value of 1 — so a few idle taps on the advance button are genuinely enough to walk out of range.
What to do: stop generating codes to "see if it works", because each attempt makes it worse. Use the service's resynchronisation flow, which usually asks for two or three consecutive codes — the RFC anticipates exactly this, noting the system "MAY require the user to send a sequence of (say, 2, 3) HOTP values for resynchronization purpose". AWS's resync screen is the familiar example. If you want the arithmetic behind both schemes, TOTP vs HOTP is the short version.
Google Authenticator, Microsoft Authenticator and Authy
Everything above holds for any TOTP app, because it describes the standard rather than any one implementation. Three apps add failures of their own on top, and if you are using one of them, these go further than this page can.
- Google Authenticator code not working — where the clock setting went, what a phone transfer does to an entry, and the QR parameters Google's own specification says its apps ignore.
- Microsoft Authenticator code not working — push approvals and six-digit codes fail for unrelated reasons, number matching cannot be switched off, and a cloud restore brings back less than the restored list suggests.
- Authy code not working — the retired desktop app, the multi-device setting a new install depends on, and a backup password that nobody can reset.
When no code will ever work: recovery options
At some point this stops being a troubleshooting problem. You are here if the clock is correct, there is only one entry, the secret came from a hand-typed key you no longer have the original of, or the phone that held it is gone. The secret you hold is not the secret the service holds, and no amount of retrying changes that. Neither does any authenticator app, ours included — an app cannot reconstruct a secret it was never given.
The route back is the account, not the code:
- Spend a backup code. This is what they are for, and they work precisely when your second factor does not, because they are a bypass rather than a second copy of it. Check your password manager, your downloads folder, printouts, and any file with "recovery" in the name. Where to store your 2FA backup codes covers what to do the moment you spend one, and how to regenerate a set — you have never needed the old set to get a new one, only a session you are already signed into.
- Try a second factor you forgot you had. Many accounts allow more than one: another authenticator, a security key, a trusted device still signed in. An active session elsewhere is often enough to add a new authenticator without any formal recovery at all.
- Use the provider's recovery process. Identity checks, waiting periods, sometimes a support ticket. Lost your phone? How to get your authenticator codes back walks the per-service routes and sets honest expectations: days rather than minutes for anything financial.
Do step 1 before step 3 if you possibly can. The gap between them is the difference between ten seconds and a week. And if step 3 stalls because the recovery mail lands in an inbox that wants a code from the same app, that is a recovery-channel ring rather than a code problem: locked out of email and 2FA has the order of operations for it.
Frequently asked questions
Why does my authenticator code say invalid?
Nearly always one of two things: the device clock has drifted far enough that your app and the service are computing different codes, or the entry in your app is a retired one left over from an earlier enrolment. Rule out the clock first, in the operating system rather than in the app, because it is the cheaper of the two to check, then search your app for the service name and see whether it appears twice.
Do 2FA codes depend on my time zone?
Not directly. A TOTP code is computed from Unix time, which is counted from a fixed moment in UTC, and RFC 6238 requires that both sides can derive it: the prover and verifier MUST know or be able to derive the current Unix time (RFC 6238 §3). Two correctly set phones in different zones therefore produce the same code for the same account. The zone matters only through the clock, because on a phone the two are usually set together, so a zone chosen by hand tends to drag the absolute time with it.
Can I fix a 2FA code without the old phone?
Only if the secret exists somewhere other than that phone: a synced vault, a second device you enrolled at the same time, or a setup key you saved. If it does not, no app can rebuild it, and the way back is the account rather than the code — a backup code, another registered second factor, or the service's own recovery process.
How long is a 2FA code valid for?
The displayed code changes every 30 seconds by default, but how long a verifier will still accept one after that is a separate setting on its side, and it is rarely published. Some allow a single step either side, which is roughly a 90-second span in total; others are considerably more generous. Nothing on your side can widen it, so treat a code with a few seconds left as one to skip.
Why do my codes work on one site but not another?
Because the clock is shared between your entries and the secrets are not. If one service refuses a code while everything else is accepted, the cause is that entry or that verifier: a retired secret, a key that was typed in rather than scanned, a service using non-default settings, or an acceptance window tighter than its neighbours.
Does a rejected code mean somebody is in my account?
No, and the causes on this page are overwhelmingly mundane ones. What is worth doing once you are back in is looking at the account's recent sign-in activity and the list of second factors registered on it, because an unfamiliar entry in that list is the signal that actually matters.
Where KeyNesta fits, and what it cannot do
KeyNesta is a TOTP and HOTP authenticator, and the limits here matter more than the features.
The code is a local calculation. Generating one uses the secret and the device clock, both of which are already on the device — no account, no network request, no telemetry, nothing reported anywhere. The features page puts it as: the app works "on a plane, on a phone with no SIM, or with the network off entirely". The corollary is the honest part: KeyNesta reads your device clock and never sets it, so when the clock is wrong the fix is in the operating system, not in this app or any other.
KeyNesta cannot widen another service's acceptance window. Nobody's authenticator can. That dial lives on the verifier, and the only thing any app can do about it is be accurate and let you submit quickly.
It has no passkeys and no security keys. Neither is on the shipped list, and if the account you are locked out of offers one as an alternative factor, that is a route out of this page rather than something KeyNesta provides.
What it does do bears on three of the six causes above. Entries carry the algorithm, digit count and period the QR specified rather than the common defaults, so a SHA-256 or eight-digit entry is not silently wrong. Search is ranked across entry name, issuer, account name, tags and the full group path, and entries live in spaces and groups, which is what makes two accounts at one provider distinguishable at a glance instead of two identical rows. HOTP entries advance only when you press the button, so the counter does not run away on its own.
What it cannot do is recover anything for you. Sync is zero-knowledge: the server holds ciphertext and no key that opens it, so a forgotten passphrase is not a support ticket — what zero-knowledge costs you is the long version of that bargain, and 2FA backup and sync is how you avoid needing it. The short help-centre version of this page lives at why are my codes being rejected, and the web app at app.keynesta.com needs no sign-up if you want to test an entry against a second app.
Takeaway
Fix the clock first, because it really is most of them, and fix it in the operating system rather than in a menu your authenticator may no longer have. Then run the one diagnostic that matters: every service failing points at the device, one service failing points at that entry. After that the list is short and finite — a retired entry still counting down, two accounts wearing the same label, a code submitted a second too late, a verifier with less slack than you assumed, a hand-typed secret with a character base32 does not contain, or an HOTP counter that walked. And when none of it applies, stop retrying. Spend a backup code, because every attempt after the secret is wrong is just a slower way of arriving at the same recovery process.