# Supabase Auth: bad_oauth_state

> Supabase returns bad_oauth_state when the OAuth state is invalid, not found or expired after Google or GitHub sign-in. Restart sign-in and check the URLs.

Canonical: https://app369.com/fix/supabase-bad-oauth-state/
Last updated: 2026-11-09

bad_oauth_state is the Supabase Auth error code for an OAuth callback whose state value Supabase can’t match to a sign-in it started. The current Auth server returns it with the messages “OAuth state parameter is invalid”, “OAuth state not found or expired” or “OAuth state has expired”.

**Short answer**

Always start social sign-in with signInWithOAuth so Supabase creates the state. On the page the user lands on, read error_code from the URL and show a Sign in again button for bad_oauth_state. Make sure the provider’s callback URL is the callback of this Supabase project, and that users aren’t sent back to an old callback link.

Rather not fix it yourself? [**App Fix Ticket**](https://app369.com/fixed-price/flutter-firebase-bug-fix/) starts with a fixed-price diagnosis, then a fixed price for the fix before any fix work.

## **Why Supabase rejects the state, and the fix**

1. 01 ### **The sign-in took too long** Each OAuth state expires; the Auth server never sets the limit below five minutes. A user who stops at the provider’s login or 2FA screen comes back to “OAuth state has expired”. Catch the error and restart sign-in.```
const params = new URLSearchParams(window.location.search);
if (params.get('error_code') === 'bad_oauth_state') {
  showRetry(() => supabase.auth.signInWithOAuth({
    provider: 'google',
    options: { redirectTo: \`${location.origin}/auth/callback\` },
  }));
}
```
2. 02 ### **The app made its own state**
  > “OAuth state (data echoed back by the OAuth provider to Supabase Auth) is not in the correct format.” [**Supabase docs, Auth error codes (bad_oauth_state)**](https://supabase.com/docs/guides/auth/debugging/error-codes) Custom OAuth code that sends the user to Google with its own state value fails, because Supabase only accepts the state ID it created. Let signInWithOAuth build the provider URL.
3. 03 ### **The callback belongs to another project** A staging and a production project share one OAuth client, and the provider sends users to the wrong callback. That project has no record of the state, so it returns “not found or expired”. Use one OAuth client per project, or list each callback URL exactly.
4. 04 ### **The error lands on the Site URL** Also check: when the state fails, Supabase can’t read the redirectTo address saved with it, so users land on the Site URL, or the external redirect URL if one is set. Read the error there too. A missing state returns bad_oauth_callback, and a reused PKCE state returns flow_state_already_used.

Checked against the vendor’s docs on November 9, 2026: [Supabase docs: Auth error codes](https://supabase.com/docs/guides/auth/debugging/error-codes); [Supabase Auth source: external.go (state checks)](https://github.com/supabase/auth/blob/master/internal/api/external.go); [Supabase Auth source: configuration.go (flow state expiry)](https://github.com/supabase/auth/blob/master/internal/conf/configuration.go); [Supabase docs: PKCE flow](https://supabase.com/docs/guides/auth/sessions/pkce-flow).

## **Rather hand it over?**

Fixed scope, fixed price, paid upfront. The work happens in writing; no call needed.

- [from $450**App Fix Ticket**One reproducible bug in an existing mobile or web app, diagnosed and fixed.**See scope and start**](https://app369.com/fixed-price/flutter-firebase-bug-fix/)
- [from $450**AI-Built App Rescue**A Lovable, Bolt or Cursor app checked end to end in 3 days, then its worst problems fixed at a fixed price.****No issues worth fixing, no charge.**** If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.**See scope and start**](https://app369.com/fixed-price/ai-app-rescue/)

[**All 127 Fiverr reviews**](https://app369.com/reviews/)

Related: [**Supabase invalid flow state (code verifier)**](https://app369.com/fix/supabase-invalid-flow-state-code-verifier/) · [**Supabase OAuth provider disabled**](https://app369.com/fix/supabase-oauth-provider-disabled/) · [**Google OAuth redirect_uri_mismatch**](https://app369.com/fix/google-oauth-redirect-uri-mismatch/) · [**Supabase PGRST200**](https://app369.com/fix/supabase-could-not-find-relationship-pgrst200/)

Questions

## **More on this error**

<details>

<summary>**Is bad_oauth_state a Google or GitHub error? **+</summary>

No. The error comes from Supabase Auth rejecting the state value when the user came back to its callback.

</details>

<details>

<summary>**Should the state lifetime be raised? **+</summary>

Rarely. Self-hosted Auth can set a longer flow state expiry, but a retry button fixes the usual case of a slow sign-in.

</details>

<details>

<summary>**Can you fix it for me? **+</summary>

If one bug is the whole problem, the App Fix Ticket covers it: a written diagnosis first, then the fix. If the app has more going on, the Launch Check is a written check of the whole app. Each issue found is rated critical, high, medium or low, with where it is and how it was confirmed. No issues worth fixing, no charge. If the Launch Check finds nothing rated medium or higher, Simon refunds the full $450. You keep the report either way. This applies to the first 10 Launch Checks bought after October 30, 2026.

</details>

A different error?

## **Describe it and get a written quote**

Send the error and what you were doing. You get a written scope, a fixed price and a timeline; Simon replies by email, usually within one business day.

[**Describe your problem **→](https://app369.com/contact/) [**All fixes**](https://app369.com/fix/)