Applications and operations

Fix “relation does not exist”

Check the current database, schema path, migrations, and PostgreSQL identifier folding before changing a query.

The error looks like this:

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

PostgreSQL says “relation does not exist” when it cannot resolve the table name in the current connection. Read that carefully: not “the table does not exist anywhere”, but “I cannot find it from where this connection stands”. The table is usually fine. The connection is looking in the wrong place.

Check where you are before changing the query

Check the connection and visible tables first:

SELECT current_database(), current_schema();
SHOW search_path;
\dt *.*

These four lines resolve most cases. \dt *.* lists tables in every schema, so you can see where the table actually lives.

Three outcomes, three fixes.

If app.notes exists but notes fails, fix the search_path or qualify the table as app.notes. The table is there; your session’s path just does not include its schema.

If the table is absent from this database entirely, check current_database() against what you expected. With several environments and local clusters around, running migrations against postgres while the application connects to notes_app is an everyday mistake. Run the expected migrations against this database.

If the table exists with strange casing, keep reading.

The identifier folding trap

PostgreSQL folds unquoted identifiers to lowercase. CREATE TABLE Notes creates notes, while CREATE TABLE "Notes" creates a case-sensitive name that always needs quotes.

The painful combination is a table created with quotes, usually by an ORM or a GUI tool, then queried without them:

SELECT * FROM Notes;
-- ERROR:  relation "notes" does not exist

SELECT * FROM "Notes";
-- works

The unquoted Notes folds to notes, which does not exist; only "Notes" does. The error message even shows you the folded name in quotes, which is your clue.

My advice is to use lowercase unquoted names. Do not add quotes until you know the table was created with a quoted mixed-case name; adding quotes to a query against an ordinary lowercase table creates the same error in reverse.

After any fix, verify with the failing statement itself, then with \d app.notes to confirm you are looking at the table you think you are.

Lesson completed

Take this course offline

Get every free book, course edition, and software download.

Get the download library →