Replies: 3 comments
Root Cause Analysis & Resolution: PostgREST PGRST303 Clock SkewThe symptom where Supabase Auth ( Here is the exact architectural and code-level breakdown of why this happens, why your legacy keys still function, and how to resolve it immediately. 1. Code-Level Root Cause in PostgRESTIn PostgREST's Haskell source code ( claim "iat" IatClaimNotNumber $ inTheFuture JWTIssuedAtFuturewhere the future check is defined as: inTheFuture = checkTime ((now + allowedSkewSeconds) <)
allowedSkewSeconds = 30 :: Int64When a request arrives at If
2. Why GoTrue Accepts the Token (HTTP 200) but PostgREST Rejects ItOn hosted Supabase infrastructure, GoTrue (Auth), PostgREST (Data API), and PostgreSQL run as distinct containerized services:
3. Why Legacy
|
|
I can't find the cause in Supabase's docs, so here is a way to narrow it down rather than a fix.
|
|
The PostgREST docs explain the asymmetry. PostgREST validates the time-based claims That explains everything you saw:
Your laptop's clock doesn't matter, because both the minting and the checking happen server-side. To prove it in one request, decode the access token and compare TOKEN=... # user access token
curl -si "$SUPABASE_URL/rest/v1/profiles?select=id&limit=1" \
-H "apikey: $PUBLISHABLE_KEY" -H "Authorization: Bearer $TOKEN" | grep -i '^date:'
# then: echo "$TOKEN" | cut -d. -f2 | base64 -d 2>/dev/null -> look at "iat"If Two things not to do while you wait:
Also make sure the publishable or secret key goes in the |
Uh oh!
There was an error while loading. Please reload this page.
Hello,
I'm experiencing an issue that completely prevents users from accessing my application.
Using the exact same user access token and publishable API key, direct requests produce different results:
GET /auth/v1/user → HTTP 200, authenticated user returned.
GET /rest/v1/profiles?select=role&id=eq. → HTTP 401, PGRST303: JWT issued at future.
These tests were performed directly, independently of the application's frontend authentication and role-loading logic.
Additional findings:
The PostgreSQL database is accessible through the Supabase dashboard.
The local machine and database clocks are consistent.
The legacy service_role JWT successfully accesses the database RPC.
An sb_secret_ API key previously received the same PGRST303 error.
The organization is below its Free Plan usage limits.
The issue persists in a private browsing session.
Project reference: vjddbwdfapneeddqhpho
Latest reproduction: October 17, 2026, approximately 20:22 UTC.
Could someone from the Supabase team investigate why PostgREST rejects a JWT that Supabase Auth accepts, specifically reporting that it was issued in the future?
Is there a known issue involving JWT timestamp validation or clock synchronization between Auth and the Data API?
The issue is currently blocking access to my application.
Thank you.
All reactions