Postgres "relation does not exist" for a table that exists: search_path, quoted identifiers, and the role that cannot see it
Problem
The table exists — \dt in psql lists it. The application still gets:
ERROR: relation "orders" does not exist
LINE 1: SELECT * FROM orders LIMIT 1;
# psql \dt as the same user: SHOWS ordersWorks via psql, fails via the app. Two sessions, same user, same database, different answers — which means the difference is state, not permissions.
Root cause
Unqualified names resolve through search_path — the list of schemas tried in order. psql sessions and app connections can have different search paths:
1. The table lives in app_data, and the app connects with a default search_path ("$user", public) that never includes it. Your psql session had SET search_path = app_data, public; from a .psqlrc or a previous command. 2. Quoted mixed-case creation: the table was created as "Orders" (quoted, case-preserved). SELECT * FROM orders looks for lowercase orders — a different relation. It shows in \dt as Orders. 3. A pooled connection's SET search_path from one request leaks to the next — read-your-writes works for whoever ran the SET, fails for everyone else.
SHOW search_path;
… 1 more line in the fix🔒 the fix — including 4 code blocks — is members-only. $1/mo unlocks everything.