Skip to content

Supabase API errorSupabase: “JWSError JWSInvalidSignature” (PGRST301)

Every database request suddenly fails with 401, JWSError JWSInvalidSignature, or PostgREST code PGRST301. The project couldn’t verify the token your app sent: it was signed by a different project, or by a secret this project no longer uses. It usually follows a key change or a mix-up between a dev and a production project. Here’s each cause, in Supabase’s words, or hand it over at a fixed price.

Short answer

The token in the request wasn’t signed by this project’s current key. Check that the Supabase URL and the API key in production come from the same project, copy the current key from Settings, then API Keys, and redeploy. If the legacy JWT secret was changed, replace the anon and service_role keys everywhere and have users sign in again.

Where the bad signature comes from

  1. 01

    The URL and the key are from different projects

    “Provided JWT couldn't be decoded or it is invalid.” Supabase, PostgREST error codes

    A frequent mix-up: production points at one project’s URL with another project’s anon key, often a dev key left in a host’s settings. Check both values in the production environment variables, then redeploy, since front-end builds bake them in.

  2. 02

    The legacy JWT secret was changed

    “anon and service_role must be rotated simultaneously.” Supabase, JWT signing keys

    The legacy anon and service_role keys are tokens signed with the project’s JWT secret. Changing that secret makes the old keys and every signed-in user’s token fail at once. Put the new keys in every app, server and function that used the old ones.

  3. 03

    Old sessions from before the change

    “Currently active users get immediately signed out.” Supabase, JWT signing keys

    After a legacy secret change, browsers and phones still hold tokens signed with the old secret. Supabase’s comparison says active users are signed out. Handle a 401 by signing out and sending the user back to sign-in.

  4. 04

    Your own code checks tokens with the old secret

    “Make sure your app does not directly rely on the legacy JWT secret.” Supabase, JWT signing keys

    If a server, Edge Function or other service verifies or creates tokens with the legacy JWT secret, moving to the new signing keys breaks it. Verify Supabase tokens with getClaims() or the project’s published keys instead.

  5. 05

    A key pasted in the wrong format

    “Publishable and secret keys are short strings, not JWTs.” Supabase, API keys

    Supabase’s newer publishable and secret keys are short strings, not tokens. Code or a tutorial written for the old eyJ keys can end up sending one of them as the Authorization bearer token, or a pasted key picks up a stray space, quote or line break. Check that apikey and Authorization hold exactly the key from API Keys, with nothing added.

Checked against the vendor’s docs on : Supabase docs: PostgREST error codes; Supabase docs: JWT signing keys; Supabase docs: API keys.

Rather hand it over?

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

Related: Supabase Invalid Refresh Token logouts · Supabase anon key exposed · Supabase service role key exposed · Supabase Email address is invalid

Questions

More on this error

Is this the same as an expired session?

No. An expired token is one the project signed that ran out of time. JWSInvalidSignature means the project can’t verify who signed the token at all, so refreshing the session won’t help until the key or project mismatch is fixed.

Should I change the JWT secret to fix it?

Not to fix this. Changing the legacy secret is what often causes it. Change it only if the secret leaked, and then follow Supabase’s signing keys guide so users aren’t all signed out at once.

Can you fix it for me?

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.

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; we reply by email, usually within one business day.