Fix PostgreSQL ERROR: relation "table_name" does not exist

beginner๐Ÿ˜ PostgreSQL2026-03-18| PostgreSQL 12+, Linux/macOS/Windows, psql CLI, pgAdmin, any PostgreSQL client

Error Message

ERROR: relation "table_name" does not exist
#postgresql#table#schema#relation

The Error

ERROR: relation "table_name" does not exist
LINE 1: SELECT * FROM table_name;
                      ^

Running a query you know should work โ€” and PostgreSQL says the table doesn't exist. You can see it right there in pgAdmin. Four things cause this almost every time, and none of them mean your data is gone.

Why This Happens

PostgreSQL found your query but can't resolve the table reference. The table might be perfectly intact. The problem is usually one of these:

  • The table lives in a different schema and your search_path skips it
  • Case sensitivity โ€” the table was created with a quoted mixed-case name like "Users"
  • You're connected to the wrong database (happens constantly in multi-environment setups)
  • The table genuinely doesn't exist โ€” the migration never ran, or ran against the wrong environment
  • It's a temporary table from another session โ€” temp tables are session-scoped and invisible elsewhere

Step-by-Step Fix

Step 1: Check If the Table Actually Exists

Before anything else, confirm the table is actually there:

-- List all tables across all schemas
SELECT table_schema, table_name
FROM information_schema.tables
WHERE table_name = 'your_table_name';

Or in psql:

\dt *.*

No results? The table doesn't exist. Check your migration files or run the CREATE TABLE statement manually.

Step 2: Check Your Schema and Search Path

PostgreSQL defaults to looking in the public schema. Many production setups use custom schemas โ€” app, api, reporting โ€” and if search_path doesn't include them, every query against those tables fails with this error.

-- See current search path
SHOW search_path;

-- See which schema you're in right now
SELECT current_schema();

Table is in a schema called app? Three options:

-- Option A: Prefix the table name explicitly
SELECT * FROM app.users;

-- Option B: Add schema to search path for this session
SET search_path TO app, public;
SELECT * FROM users;

-- Option C: Make it permanent for the current user
ALTER ROLE your_user SET search_path TO app, public;

Step 3: Check for Case Sensitivity

This one catches everyone eventually. PostgreSQL lowercases all unquoted identifiers โ€” so Users, users, and USERS all resolve to the same thing. The exception: tables created with double quotes.

-- Created like this:
CREATE TABLE "Users" (id serial, name text);

-- This FAILS (PostgreSQL looks for lowercase "users"):
SELECT * FROM users;

-- This WORKS:
SELECT * FROM "Users";

Find the exact stored name:

SELECT table_name FROM information_schema.tables
WHERE table_schema = 'public';

Mixed-case names in the results mean quoting them in every single query. The easier long-term fix: stick to lowercase with underscores when creating tables โ€” user_accounts, not UserAccounts.

Step 4: Make Sure You're in the Right Database

Each PostgreSQL database is completely isolated. A table in db_production is invisible from a connection to db_staging โ€” even on the same server. This is a classic trap in Docker and CI pipelines where DATABASE_URL quietly points somewhere unexpected.

-- Check current database
SELECT current_database();

-- In psql, switch database (requires reconnection)
\c correct_database_name

Using a connection string in your app? Double-check the database name in your .env or config file.

Step 5: Check If It's a View or Sequence

The same error fires when referencing a missing view or sequence. Search across all object types at once:

SELECT schemaname, tablename, 'table' AS type FROM pg_tables WHERE tablename = 'target_name'
UNION ALL
SELECT schemaname, viewname, 'view' FROM pg_views WHERE viewname = 'target_name'
UNION ALL
SELECT schemaname, sequencename, 'sequence' FROM pg_sequences WHERE sequencename = 'target_name';

Verify the Fix

Quick sanity check after making changes:

-- Should return rows or an empty set โ€” not an error
SELECT * FROM your_schema.your_table LIMIT 5;

-- Confirm you're in the right schema and database
SELECT current_schema(), current_database();

Changed search_path for a role? Disconnect and reconnect to confirm it persists.

Quick Tips

  • Name tables in lowercase with underscores โ€” user_orders, not "UserOrders". Eliminates case sensitivity issues permanently.
  • Explicit schema prefixes (schema.table) are more reliable than search_path, especially in app code that runs across multiple environments.
  • Before running migrations, run SELECT current_database(), current_schema(); to confirm you're targeting the right place.
  • In Docker or CI, a misconfigured DATABASE_URL pointing to the wrong database is the #1 cause of this error outside local development.
  • Django and SQLAlchemy both support explicit schema config โ€” check Meta.db_table or __table_args__ if queries work in psql but fail in your app.

Related Error Notes