Supabase otp_expired: OTP code for this sign-in has expired
Supabase returns otp_expired on a magic link or email code? That code has expired. Supabase says to sign in again. The default lifetime is 1 hour.
Reviewed October 21, 2026
What it means in plain English
Supabase Auth's error code otp_expired means the OTP code for this sign-in has expired. The error-codes guide says to ask the user to sign in again, and to branch on error.code rather than matching the message text.
Email magic links and email one-time passwords share that expiry. Supabase's passwordless guide says a user can request one once every 60 seconds, and they expire after 1 hour by default. The same Email OTP expiration setting also governs magic links and the other email links: confirmation, password recovery, email change, and invitation.
Likely causes
- The person opened the link or entered the code after that expiry.
- Email OTP expiration is still the default 1 hour, and the inbox was checked later than that.
- The request is a different limit.
over_email_send_rate_limitmeans too many emails were sent to this address.over_request_rate_limitmeans too many requests from this client. - The error is not about expiry at all. A magic-link or OTP request for an email with no account, with shouldCreateUser set to false, fails with Signups not allowed for otp.
How to fix it, step by step
- Read
error.code. Treatotp_expiredas an expired code. Ask the person to request a new sign-in. - Open Authentication, then Sign In / Providers, then Auth Providers, then Email, then Email OTP expiration. Supabase says that is where the duration is set. A value above 86,400 seconds (one day) is strongly discouraged and can only be set with the Management API.
- Leave the 60-second request spacing in place. Sending the same address another code inside that window is a different failure.
- If the new link opens
localhost, the Site URL is a separate setting. See Supabase login redirects to localhost:3000 after deploy. - If the code is
over_email_send_rate_limit, wait before sending another email to that address. See email rate limit exceeded (Supabase Auth).
How to check it worked
- A new magic link or email code, used inside the expiry you set, returns a session.
error.codeon a late attempt isotp_expired, and a fresh request signs the person in.
Sources
Related fixes
More Supabase auth and email fixes
Keep going on your own.
The guides stay free. A deep leak report is $15. Fix packs are $24, or $49 for all three. There is no done-for-you repair.