supabase/supabase · error · Error

The user does not exist

Error message

The user does not exist

What it means

Thrown after getUserClaims returns no error but also no claims object — meaning the token was syntactically processed but resolved to no known user. Distinct from [183] (no token at all) and from a token-parse error; here the JWT is present but the user lookup is empty.

Source

Thrown at apps/studio/lib/api/apiAuthenticate.ts:48

  }
}

/**
 * @returns
 *  user with only id prop or detail object. It depends on requireUserDetail config
 */
export async function fetchUserClaims(req: NextApiRequest): Promise<JwtPayload> {
  const token = req.headers.authorization?.replace(/bearer /i, '')
  if (!token) {
    throw new Error('missing access token')
  }
  const { claims, error } = await getUserClaims(token)
  if (error) {
    throw error
  }

  if (!claims) {
    throw new Error('The user does not exist')
  }

  return claims
}

View on GitHub (pinned to beee91b9c2)

Solutions

  1. Force a fresh session on the client: call supabase.auth.signOut() then re-authenticate, so a new JWT is issued.
  2. Verify the user still exists in the auth.users table and the token's sub matches an active account.
  3. Check that AUTH_JWT_SECRET / JWKS config on the server matches the issuer of the token.
Defensive patterns

Strategy: try-catch

Validate before calling

// Client-side: proactively refresh before assuming the session is valid
const { data: { session } } = await supabase.auth.getSession()
if (!session?.user) {
  // force re-login instead of sending a doomed request
}

Type guard

const hasValidClaims = (c: unknown): c is { sub: string } =>
  typeof c === 'object' && c !== null && typeof (c as any).sub === 'string'

Try / catch

try {
  const claims = await fetchUserClaims(req)
} catch (e) {
  if (e instanceof Error && e.message === 'The user does not exist') {
    // prompt re-auth; the account is unknown or the token is stale
    return res.status(401).json({ error: { message: 'Re-authentication required' } })
  }
  throw e
}

Prevention

When it happens

Trigger: A request carries a bearer token, but the token is for a deleted/unknown user, an expired/revoked session that still parses, or a token minted by a different auth instance. getUserClaims succeeds without error yet yields claims === null/undefined.

Common situations: User account was deleted but the client still holds an old JWT; auth provider keys rotated so the token verifies against the wrong audience; a stale localStorage session survives across a user-merge or org migration.

Related errors


AI-assisted analysis of supabase/supabase@beee91b9c2 (2026-08-12). Data as JSON: /api/errors/723ec03cd810d8e9. Report an issue: GitHub.