Supabase

Supabase: PGRST116, .single() got 0 or many rows

PGRST116: JSON object requested, multiple (or no) rows returned

In short: The query used .single(), which requires exactly one row, but it got none or more than one. RLS hiding the row looks the same as 'not found'.

Why it happens

supabase-js .single() asks PostgREST for a JSON object, not an array. PostgREST returns PGRST116 when the result is 0 rows or 2+ rows. AI-generated code uses .single() for 'get this user's profile' and then the profile row was never created, the filter is wrong (eq('id', userName) instead of the uuid), or RLS has no SELECT policy so the row is invisible and the count is 0. .single() on a list query (all orders, all comments) fails the other way, with multiple rows. .maybeSingle() is the helper for 'zero or one row is fine'.

How to fix it

  1. Log the full error (error.code and error.details) and the filter you sent. PGRST116 with 0 rows means 'no row this role can see'; 2+ rows means the filter is not unique.
  2. If 0 rows, look in the Table Editor (as a privileged user) for the row. If it is there, the client is failing RLS or using the wrong column or user id: check auth.uid() matches the column, and that a SELECT policy exists. If the row is missing, create it (for example a trigger on signup that inserts into profiles) instead of calling .single() on an empty table.
  3. Replace .single() with .maybeSingle() when zero rows is a normal case (no profile yet). Then check data === null and send the user through an onboarding insert.
  4. If you expected many rows, drop .single() / .maybeSingle() and use the default array result, or add a unique filter (eq('id', id) on a primary key).
  5. Retry the same query after sign-in and after sign-out. A query that only fails signed-out is a policy issue, not a .single() issue.

Example

const { data, error } = await supabase
  .from("profiles")
  .select("id, display_name")
  .eq("id", user.id)
  .maybeSingle();

if (error) throw error;
if (!data) {
  // No profile yet, or RLS hid it. Don't use .single() for this case.
}
Don't: Don't disable RLS so .single() 'finds' the row, and don't add .limit(1) on a poorly filtered query to hide the fact that several rows match.

Copy-paste fix prompt

3 · The fix promptPaste into Cursor, Claude Code, Codex, Lovable, Bolt, Replit or v0
I'm getting this error in my app:

PGRST116: JSON object requested, multiple (or no) rows returned

[Paste the full error, stack trace, and the file it points to here]

Likely cause: The query used .single(), which requires exactly one row, but it got none or more than one. RLS hiding the row looks the same as 'not found'.

Task: The query throws PGRST116 because .single() did not get exactly one row. Use .maybeSingle() when zero rows is allowed, fix the filter or the missing profile row, and check SELECT RLS if the row exists in the table but not in the API. Don't turn RLS off or silently take the first of many rows.

Rules:
- First explain the root cause in 2 sentences and list the files you'll change.
- Make the smallest change that fixes it. Don't refactor unrelated code.
- Don't disable security or checks (RLS, auth, signature verification, type checking, CORS allow-all) to make the error disappear.
- Never print or hard-code secret keys.
- Finish by telling me exactly how to verify the fix.

Common with: Cursor, Lovable, Bolt, v0, Claude Code. Last reviewed 2026-11-15.

Related fixes

← All fixes · Still stuck? Use the diagnose-first prompt