VVektorIndex
Supabase / Next.jsDatabase / Supabase🔥 Very high search volume

Supabase RLS Returns Empty Row — Multi-Tenant Policy Blocking Valid User Query

The Exact Error

PostgrestError: {
  code: 'PGRST116',
  details: 'Results contain 0 rows',
  hint: null,
  message: 'JSON object requested, multiple (or no) rows returned'
}

Expected: Row for user_id = 'usr_abc123' in tenant_id = 'ten_xyz'
Received: [] (empty — RLS blocked the query silently)

What's Happening

Supabase returns empty results or PGRST116 errors for users who should have access. The data exists in the DB but RLS is silently blocking the read.

Root Cause

Supabase RLS policies fail silently — they don't throw permission errors, they return empty results. In multi-tenant setups, a policy that checks `auth.uid()` against a tenant membership table can fail if the join is misconfigured, the tenant_id is missing from the JWT, or the policy references a column that doesn't exist in the anon role's accessible schema.

Quick Diagnosis Checklist

Run through these steps to confirm this is your issue:

1

Use Supabase RLS debugger: `SET pgrst.db_anon_role = 'authenticated'` and test directly in SQL editor

2

Check if `auth.uid()` matches the user_id in the RLS policy — log both to compare

3

Verify the tenant_id is being passed in the JWT custom claims

4

Test with `SECURITY DEFINER` temporarily to confirm data exists

5

Run `EXPLAIN (ANALYZE, FORMAT JSON) SELECT ...` to see if RLS filter is applied

The Permanent Fix

Implement automated RLS boundary tests that run in staging before every deploy — testing every tenant isolation path systematically, not just the happy path.

Drop-In Package That Permanently Fixes This

Instead of building the fix from scratch, use this production-ready package.

🧪
Multi-Tenant RLS Isolation Tester
Prove Client A can never see Client B's data — before you deploy to production.
$79
/month
What the fix looks like
// rls-tester.config.ts
import { RLSTester } from './rls-tester'

const tester = new RLSTester({
  supabaseUrl: process.env.SUPABASE_URL!,
  serviceKey: process.env.SUPABASE_SERVICE_KEY!,
  tenants: ['tenant_a_id', 'tenant_b_id', 'tenant_c_id'],
  tables: ['documents', 'invoices', 'user_profiles'],
  attacks: ['tenant_escalation', 'null_rls', 'jwt_tampering'],
  outputReport: 'compliance-audit-log.json'  // hand to auditors
})

// Run in CI before every deploy
await tester.runAll()  // throws if any isolation failure found
Setup time
60 minutes
Files included
8 files

Related Compliance Law

🌐
Multi-Tenant Database Isolation — RLS Security Requirement
NOT a deadline — a live engineering risk that can destroy your company overnight
Max fine: GDPR: €20M. POPIA: R10M. Plus class action. Plus lost customers.

Related Errors

supabase rls returns empty row multi-tenant, supabase pgrst116 rls policy blocking, supabase row level security empty result debug, supabase multi-tenant rls not working nextjs, supabase rls silent failure empty response