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
- Log the full error (
error.codeanderror.details) and the filter you sent.PGRST116with 0 rows means 'no row this role can see'; 2+ rows means the filter is not unique. - 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 intoprofiles) instead of calling.single()on an empty table. - Replace
.single()with.maybeSingle()when zero rows is a normal case (no profile yet). Then checkdata === nulland send the user through an onboarding insert. - 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). - 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.
}
.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
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.