Skip to content
SQL errors / Fix “Catalog Error: Table Does Not Exist” in SQL
SQL error

Fix “Catalog Error: Table Does Not Exist” in SQL

No table by that name is visible to the query. A typo, a missing schema, or a table that's already gone.

The exact message
DuckDB
Catalog Error: Table with name order_item does not exist! Did you mean "order_items"?
PostgreSQL
relation "order_item" does not exist
MySQL
Table 'garden_shop.order_item' doesn't exist

Error 1146. The name is prefixed with the database.

SQL Server
Invalid object name 'order_item'.
Oracle
ORA-00942: table or view does not exist
SQLite
no such table: order_item

The symptom

The query names a table the database can't find. DuckDB checks every table name before it reads a single row, so the query fails straight away, and the message tells you which name it looked for. Most of the time it's a spelling slip: Garden Shop's line items live in order_items, and the bench below asks for order_item.

The fix

Use the name the table really has:

The query that fails
select o.order_id, sum(oi.quantity)::integer as items
from orders as o
join order_item as oi on oi.order_id = o.order_id
group by o.order_id
order by o.order_id
limit 5;

Running it raises Table with name order_item does not exist.

The corrected query
select o.order_id, sum(oi.quantity)::integer as items
from orders as o
join order_items as oi on oi.order_id = o.order_id
group by o.order_id
order by o.order_id
limit 5;

Open the corrected query in the playground

Read the suggestion, carefully

DuckDB adds its closest match: Did you mean "order_items"? When the name is one letter off, that's the answer. When nothing is close, it still suggests something, and the suggestion is noise: select * from sales on Garden Shop gets Did you mean "sqlite_master"?, one of DuckDB's internal catalog views. A suggestion that looks unrelated means no table in the database is close to the name you typed.

List the tables that do exist

Ask the database instead of guessing:

Every table
show tables;
Search by part of the name
select table_schema, table_name
from information_schema.tables
where table_name ilike '%order%'
order by table_name;

On Garden Shop that finds order_items and orders, both in the main schema. More ways to look around: SHOW TABLES and DESCRIBE.

Other reasons the table isn't there

It's in a schema you didn't name, or that doesn't exist

A schema-qualified name has to match both parts. DuckDB says which part is missing:

Wrong: a schema that doesn't exist
select count(*)
from staging.orders;

That fails with Table with name "staging.orders" does not exist because schema "staging" does not exist. If the schema does exist, check that the table was created inside it and not in main. See schemas.

A CTE only lasts for one statement

A with query names a result for the statement it belongs to. The next statement can't see it:

Wrong: using a CTE in the next statement
with recent_orders as (
  select * from orders
  where order_date >= date '2024-06-01'
)
select count(*) from recent_orders;

select count(*) from recent_orders;

The first count runs. The second fails with Table with name recent_orders does not exist! Repeat the with block, or save the result with create or replace table if several queries need it.

A view's table was dropped

DuckDB lets you drop a table that a view reads from. The view stays, and fails only when you query it, naming the table you didn't type:

Wrong: a view over a dropped table
create or replace table order_snapshot as
select * from orders where status = 'shipped';

create or replace view shipped_orders as
select order_id, order_date from order_snapshot;

drop table order_snapshot;

select count(*) from shipped_orders;

The last line fails with Table with name order_snapshot does not exist! When the missing name isn't in your query, look for a view in between. PostgreSQL would have refused the drop instead. See views.

On SQLShed: the table belongs to another dataset, or you dropped it

The playground holds one practice dataset at a time. Switching from Garden Shop to Movie Rentals drops Garden Shop's tables, so a query on products that worked a minute ago fails. Switch back, or check the playground's table list for what's loaded now. A table you dropped or renamed yourself stays gone until you reload the page, which restores the dataset.

A create temp table doesn't survive to your next Run either: each Run gets a fresh connection, and temporary tables belong to the connection that made them. Use create or replace table for anything you want to query again.

Dialect note

DuckDB matches table names without regard to case, even in double quotes: select count(*) from "Customers" returns Garden Shop's 20 customers. PostgreSQL treats a quoted name as exact, so the same query fails there with relation "Customers" does not exist. Write table names in lowercase and you never meet the difference.

Guard scripts that drop and create

In a script that runs more than once, if exists turns a missing table into a no-op instead of an error:

Clean up without failing
drop view if exists shipped_orders;
drop table if exists order_snapshot;

Lesson 18.5 · Write a rerunnable script builds a whole script this way.

Functions too

A misspelled function gets the same treatment: Catalog Error: Scalar Function with name lenght does not exist! Did you mean "length"?

How other engines word it

Engine Message
DuckDB Catalog Error: Table with name order_item does not exist! Did you mean "order_items"?
PostgreSQL relation "order_item" does not exist
MySQL Table 'garden_shop.order_item' doesn't exist Error 1146. The name is prefixed with the database.
SQL Server Invalid object name 'order_item'.
Oracle ORA-00942: table or view does not exist
SQLite no such table: order_item

Related errors

Learn more