Troubleshooting
Find the cause of a sign-in or integration problem by the symptom you see.
On this page
What this section is for#
Start from what you see, on a screen or in a response, and follow the page that matches it. Each page has the same shape: the symptom, the likely causes with the exact message for each, how to tell which one it is, and the fix. It exists because errors are usually visible and causes are not, and because the sign-in pages are deliberately vague in places.
It has two kinds of reader. The first half is for people who sign in and meet a message they do not understand. The second half is for developers who see an OAuth error or a refused request in a log. Pick the page whose symptom is closest, even if the cause turns out to be different, because each page also points to its neighbours.
The mental model#
A problem has a layer, and finding the layer is most of the work. A person's problem is usually in the sign-in itself (a wrong detail, an expired link, a method the browser cannot use), in the session (it ended for a reason you can name) or in a confirmation (a second factor used too long ago). A developer's problem is usually in the request (a redirect address that does not match), in the grant (a code or refresh token that is no longer valid), in the proof (a DPoP header) or in time (a clock that is off).
person: cannot sign in | passkey missing | link expired | session ended | confirm againdeveloper: invalid_grant | redirect mismatch | DPoP | 429 | clockThree typical journeys#
I cannot sign in.
- Cannot sign in: match the message on the screen.
- Passkey not offered: if the passkey is the problem.
- If you are locked out: the way back when nothing works.
My app stopped signing people in.
- Redirect URI mismatch: the most common cause at setup.
- invalid_grant: a code or refresh token that was refused.
- Clock skew: good requests refused because of time.
Requests are being refused with no clear reason.
- 429 Too Many Requests: recover without making it worse.
- invalid_dpop_proof and use_dpop_nonce: one is a normal part of the protocol.
- Error handling: what your code should do.
What each page answers#
For people. Cannot sign in explains what each message on the sign-in pages means and how to get back in. Passkey not offered explains why the page does not offer your passkey or the browser cannot use it. Link or code expired explains how long each link and code lives (for example 15 minutes for an emailed sign-in link and 24 hours for an email verification link). Session ended unexpectedly lists the events that end a session, so you can tell which one it was. step_up_required explains why an account action asks you to confirm again and which methods can answer.
For developers. invalid_grant explains each answer for a code, a refresh token and an exchange. Redirect URI mismatch explains what the person and the developer see and how to fix the registration or the request. invalid_dpop_proof and use_dpop_nonce explains each DPoP refusal. 429 Too Many Requests explains what triggers it and how to recover. Clock skew lists the clock-dependent checks and the tolerance of each.
Before you start#
For a screen problem, note the exact words of the message, because the pages are indexed by them. For a protocol problem, have the error and error_description from the response, the endpoint and the status. Do not post tokens, keys or codes in a ticket.
Common questions#
The page says my details did not work but I am sure they are right. Why? The page never says whether an account exists, so the same message covers an unknown address. See Cannot sign in.
Why does my link not work? It works once, in the browser that asked, until it expires. See Link or code expired.
Why am I asked to confirm again? The action needs a second factor used in the last 30 minutes. See step_up_required.
Is use_dpop_nonce an error I must fix? No, it is a normal part of the protocol: sign a new proof with the nonce and send again. See invalid_dpop_proof and use_dpop_nonce.
Does a refresh that fails with invalid_grant need a retry? No. Sign the person out and start a new sign-in. See invalid_grant.
What this section does not cover#
It does not list every code, which is in the Error codes reference, and it does not explain the flows, which are in Flows. It does not diagnose problems inside your own application or hosting. If you suspect a flaw in identity itself, see Reporting a vulnerability.