Error de PostgreSQL: relation does not exist
ERROR: relation "users" does not exist
LINE 1: SELECT * FROM users;
^
PostgreSQL no encontró ninguna tabla, vista o secuencia con ese nombre entre los schemas en los que se le permite mirar. En la práctica este error rara vez significa que la tabla falta — normalmente significa que tú y PostgreSQL estáis mirando en sitios distintos.
Qué significa este error
"Relation" es el término paraguas de PostgreSQL para tablas, vistas, secuencias, índices y compañía. La resolución de nombres depende de dos piezas de contexto que la gente olvida que tiene: la base de datos actual (las relaciones viven por base de datos; no hay acceso entre bases de datos) y el search_path, la lista ordenada de schemas contra la que se resuelve un nombre no cualificado.
Más una regla de sintaxis que genera confusión sin fin: los identificadores sin comillas se plegan a minúsculas. Una tabla creada como "Users" (entrecomillada, por un ORM o una GUI) solo puede alcanzarse como "Users" — el nombre sin comillas users es un identificador distinto.
Causas comunes
- La tabla está en un schema que no está en tu
search_path(p. ej. esapp.usersy tu path es"$user", public). - Identificador con mayúsculas/minúsculas creado con comillas; las consultas sin comillas se pliegan a minúsculas y no lo encuentran.
- Base de datos incorrecta — conectado a la base de datos por defecto
postgresen vez de a la de la aplicación; todo "desaparece". - Migraciones no aplicadas en este entorno, o aplicadas a un schema distinto del que consulta la app.
- Una tabla temporal de otra sesión o de una conexión anterior (las tablas temporales son por sesión).
Cómo diagnosticarlo
SELECT current_database();
SHOW search_path;
-- ¿La relation existe en alguna parte, con cualquier combinación de mayúsculas/minúsculas?
SELECT n.nspname AS schema, c.relname, c.relkind
FROM pg_class c
JOIN pg_namespace n ON n.oid = c.relnamespace
WHERE c.relname ILIKE '%users%';
Esa última consulta lo zanja de un tirón: te dice si la relation existe siquiera, en qué schema, y con qué combinación exacta de mayúsculas/minúsculas.
Cómo solucionarlo
- Schema incorrecto → cualifica el nombre (
app.users) o fija el path de forma persistente donde corresponde:
(UnALTER ROLE app_user SET search_path = app, public; -- o bien: ALTER DATABASE appdb SET search_path = app, public;SET search_patha nivel de sesión también funciona, pero con poolers de conexiones prefiere los ajustes a nivel de rol/base de datos.) - Mayúsculas/minúsculas → entrecomíllalo exactamente (
SELECT * FROM "Users") — y adopta la convención que salva a todos: solo identificadores en minúsculas y sin comillas. - Base de datos incorrecta → arregla la cadena de conexión;
psqlsin un nombre de base de datos te conecta a una con el nombre de tu usuario del SO, o apostgres— rara vez lo que usa la app. - Migraciones faltantes → ejecútalas; la consulta de diagnóstico de arriba confirma si el schema realmente está vacío.
