# SELECT returns nothing, no error: RLS is filtering, not broken

The dashboard shows the rows, the app shows nothing, and there is no error. Agents debug the client query for an hour. The cause is nearly always one of three: no SELECT policy for the caller's role, a USING clause that matches nothing, or the wrong role entirely.

## Symptom to cause to confirmation to fix

1. Confirm the caller's role. Anon key with no JWT runs as `anon`. User JWT runs as `authenticated`. List policies `for select` and check the `to` clause includes that exact role.
2. Read the USING clause against a real row. `using (auth.uid() = owner_id)` returns only rows the caller owns. If you expected public rows, the policy is wrong, not the query.
3. Remember the dashboard SQL editor bypasses RLS (it runs as postgres). "Works in the dashboard" proves the data exists, never that the policy is right.
4. Check for conflicting policies. Multiple permissive SELECT policies OR together, so one broad policy can mask a narrow one during testing. List them all before concluding.
5. Check the JWT is actually sent. A client that dropped the Authorization header silently downgrades to anon, and anon policies return nothing for user data.

## Verification

Run the identical query three ways: dashboard (bypass, shows all), anon key (should show the public subset), user JWT (should show the user's subset). Each role's result must match the policy intent exactly.