error: relation "todo" does not exist

Node.js · updated 2026-11-10

Raised by Postgres (SQLSTATE 42P01) when a query names a table, view or sequence it cannot find in the search_path. node-postgres throws it with a position pointing at the name, psycopg raises UndefinedTable, and Django and SQLAlchemy wrap it as ProgrammingError. Typical after a deploy whose migrations did not run, or when the app points at a different database than you think.

error: relation "todo" does not exist
    at node_modules/pg/lib/client.js:694:17
    at process.processTicksAndRejections (node:internal/process/task_queues:103:5)
  code: '42P01', position: '15'

Quick fix

Compare the name in the error with the real table. Postgres lowercases unquoted names, so a table created as "Orders" (quoted) must be queried as "Orders", and select * from Orders looks for orders. If the name is right, the table is missing where you looked: the migration did not run on this database, the app is connected to another database, or the table lives in a schema outside the search_path.

  1. Read the exact name in the error. Lowercased compared with your code means a quoting problem.
  2. List what exists: \dt *.* in psql, or select table_schema, table_name from information_schema.tables.
  3. Check the connection string the failing process uses (host, database name). Staging and production are often mixed up.
  4. Run the migrations against that database (prisma migrate deploy, python manage.py migrate, alembic upgrade head, or your tool).
  5. Table in another schema: qualify it (analytics.events) or add the schema to search_path.

Why it happens

Migrations did not run

The code that uses the new table shipped, but the migration that creates it never ran on this database.

Case folding

A table created with a quoted mixed-case name ("Orders", common with ORMs) is not found by an unquoted query, which Postgres lowercases to orders.

Wrong database or schema

DATABASE_URL points at another database, or the table is in a schema that is not in the search_path for this role.

A typo or a renamed table

The query uses an old name or a misspelling (todo for todos).

Other fixes

  • Through Supabase's API (supabase.from(...)) a missing table shows up as PostgREST error PGRST205, "Could not find the table ... in the schema cache", not as this message. Check the name, and reload the schema cache after creating the table outside a migration.
  • In tests, create the schema before the first query (run migrations in the test setup).

Same error, other wording

  • psycopg.errors.UndefinedTable: relation "todo" does not exist
  • django.db.utils.ProgrammingError: relation "app_order" does not exist
  • relation "orders" does not exist (table created as "Orders")

Let your coding agent catch the next one

Runheed records this error in production with the stack trace, the breadcrumbs before it and, when you set it, the agent session that shipped the code, and serves it to Claude Code, Cursor or any MCP client. With it connected, you can ask:

> Find the "relation does not exist" errors, tell me which table names they use and which database each process was connected to, and fix the name, the quoting or the missing migration.

Setup for Node.js and Express or Vercel Functions, then have your agent fix and resolve it.

Related errors

More in Databases

References: PostgreSQL docs: identifiers and case folding, PostgreSQL docs: schema search path, PostgREST docs: error codes (42P01 and PGRST205)

Spotted a mistake? Email hello@greatwork.company. About Runheed.