Fix guides / Supabase: "JWT expired" (PGRST301)

How to fix Supabase "JWT expired"

Everything works, then after about an hour requests fail with JWT expired (PGRST301) or a 401. Refreshing the page fixes it for a while. The user's access token expired and your app kept using the old one.

Why it happens

Supabase access tokens last one hour by default. The supabase-js client refreshes them automatically, but only if you let it. AI-built apps often break this by:

  • Copying the access token into their own state, localStorage key, or an Authorization header, then reusing that stale string.
  • Creating a new client with autoRefreshToken: false or persistSession: false.
  • Server code (Next.js, Edge Functions) that reads the token from a cookie but never writes the refreshed one back.
  • A computer clock that is badly wrong, so tokens look expired.

Fix 1: use one client and let it manage tokens

// lib/supabase.ts, import this everywhere
import { createClient } from '@supabase/supabase-js';
export const supabase = createClient(URL, ANON_KEY, {
  auth: { autoRefreshToken: true, persistSession: true },
});

Remove any code that saves session.access_token yourself. When you need a token for your own API, ask for it at call time: const { data } = await supabase.auth.getSession();

Fix 2: Next.js server side

Use @supabase/ssr with a middleware that calls supabase.auth.getUser() on each request and sets the returned cookies on the response. That is what refreshes the session for server components.

Fix 3: Edge Functions

Pass the user's current token from the client on each call (supabase.functions.invoke does this for you) instead of a token stored at login.

Check the fix

  1. In Authentication settings, temporarily set a short JWT expiry if your plan allows it, or leave a tab open for over an hour.
  2. Use the app again; requests should succeed without a reload.
Still stuck? No shame in it: these bugs hide in places your AI builder cannot see. Send me the error and your repo and I will fix it as a pull request within 24 hours, explained in plain English, for $49. Several things broken? The $149 Full Rescue covers up to 3 issues plus a security pass, within 72 hours. Not fixed means full refund.
Quick Fix, $49Full Rescue, $149Ask first

Last updated 2026-10-21.