DuckDB could not find the table, view, column, function, schema, or sequence you named. The catalog is DuckDB's index of every named object it knows about, and this error means the name in your query is not in it.
The wording varies by which kind of catalog entry is missing, but every variant starts with Catalog Error and names the specific object type. DuckDB usually appends a fuzzy-match suggestion.
Catalog Error: Table with name orders does not exist!
Did you mean "main.order"?
Catalog Error: Table "customers" does not have a column named "emial"
Did you mean "email"?
Catalog Error: Scalar Function with name read_excel does not exist!
Did you mean "read_text"?
Catalog Error: Schema with name analytics does not exist!
# Python client variant:
duckdb.CatalogException: Catalog Error: Table with name orders does not exist!duckdb catalog error, duckdb catalog exception, CatalogException, Table with name does not exist, Schema with name does not exist, Function with name does not existRanked most-likely first.
Simplest and most common. DuckDB folds unquoted identifiers to lowercase but preserves case for double-quoted ones. If a table was created as CREATE TABLE "MyTable", then SELECT * FROM MyTable looks up mytable and misses. The Did you mean suggestion in the error usually points straight at the real name.
DuckDB supports multiple attached databases and multiple schemas per database. An unqualified name resolves against the current catalog and search_path only. A table in the analytics database or the raw schema needs analytics.main.orders or raw.orders, unless you first USE it.
In-memory databases are private to the connection unless opened as a shared in-memory instance. If one script creates a table on con1 and another script queries on con2, con2 sees an empty catalog. Same pattern with Jupyter notebooks when the kernel restarts between cells.
Opening DuckDB with no file gives you an empty in-memory catalog. If you meant to open orders.duckdb, you need duckdb.connect('orders.duckdb') or an ATTACH statement. A wrong path opens a fresh empty database rather than erroring.
read_excel, ST_Point, read_json_auto with certain modes, iceberg_scan, and other functions ship in optional extensions. Until you INSTALL and LOAD the extension, DuckDB reports the function as a missing catalog entry with a Did you mean suggestion pointing at a similar built-in name.
A CREATE OR REPLACE with a typo, an ALTER TABLE ... RENAME TO, or a stale migration will leave the old name gone. If the missing name looks like an older version of an object, check the migration history.
DuckDB's Python client can query pandas or polars DataFrames by variable name, but only inside con.execute or con.sql on the same connection that has the variable in scope. Passing the query string across connections, threads, or subprocesses drops the reference and the catalog lookup fails.
Confirm the object is really missing before assuming a bug. These queries show you every table, schema, and attached database DuckDB currently knows about.
SHOW DATABASES;
SHOW SCHEMAS;
SHOW TABLES;
-- Or query information_schema for a specific name:
SELECT table_catalog, table_schema, table_name
FROM information_schema.tables
WHERE table_name ILIKE '%order%';
-- For a missing function:
SELECT function_name, function_type, database_name
FROM duckdb_functions()
WHERE function_name ILIKE '%read_excel%';If SHOW DATABASES lists more than one entry, unqualified names only resolve against the current one. Fully qualify with catalog.schema.object, or switch context with USE.
-- Fully qualified:
SELECT * FROM analytics.main.orders;
-- Or switch context for the session:
USE analytics;
SELECT * FROM orders;
-- If the database is not attached yet:
ATTACH 'analytics.duckdb' AS analytics;DuckDB is case-insensitive for unquoted identifiers, but it preserves case for quoted ones. If a name was created with double quotes and mixed case, every reference has to use the same quoted form.
-- These all resolve to the same table (unquoted, lowercased):
SELECT * FROM Orders;
SELECT * FROM ORDERS;
SELECT * FROM orders;
-- But this created a distinct, case-sensitive name:
CREATE TABLE "MyTable" (id INT);
-- So this fails:
SELECT * FROM MyTable; -- looks up "mytable"
-- Match the original quoting:
SELECT * FROM "MyTable";If the missing entry is a function like read_excel, ST_Point, or iceberg_scan, the fix is to install the extension that provides it. INSTALL downloads it once, LOAD activates it for the current session.
-- Excel reader:
INSTALL excel;
LOAD excel;
-- Spatial functions:
INSTALL spatial;
LOAD spatial;
-- List everything currently loaded:
SELECT extension_name, loaded, installed
FROM duckdb_extensions()
WHERE loaded OR installed;If SHOW TABLES is empty and you expected data, you probably opened a new in-memory instance instead of your file. Pass the path to connect() or ATTACH the file explicitly.
import duckdb
# Wrong: brand new empty in-memory database
con = duckdb.connect()
# Right: open the persistent file
con = duckdb.connect('warehouse.duckdb')
# Or from an in-memory session, attach it:
con = duckdb.connect()
con.execute("ATTACH 'warehouse.duckdb' AS warehouse")
con.execute("USE warehouse")When querying a pandas or polars DataFrame from Python, either query it on the connection that has it in scope, or register it explicitly so it lives in the catalog by a stable name.
import duckdb
import pandas as pd
df = pd.read_csv('orders.csv')
con = duckdb.connect()
# Register the DataFrame as a named view:
con.register('orders', df)
con.execute("SELECT COUNT(*) FROM orders").fetchall()
# Or query directly on the module (works only in the caller's scope):
duckdb.sql("SELECT COUNT(*) FROM df").fetchall()If a migration or a stray DROP removed the object, the fix is to recreate it. Guard future runs with IF NOT EXISTS or CREATE OR REPLACE so a repeat run stops erroring.
CREATE TABLE IF NOT EXISTS orders (
id BIGINT PRIMARY KEY,
customer_id BIGINT,
total DECIMAL(10, 2),
created_at TIMESTAMP
);
-- Or replace on every run for a reproducible setup:
CREATE OR REPLACE VIEW recent_orders AS
SELECT * FROM orders WHERE created_at > now() - INTERVAL 30 DAY;Prefer unquoted identifiers when creating tables, columns, and functions. DuckDB folds them to lowercase and lookups become case-insensitive, which removes an entire class of catalog errors without any effort at query time.
For persistent workloads, always open DuckDB with a real file path and log which catalog you attached at startup. A misconfigured connection string opening a fresh in-memory database is one of the most common ways this error surfaces in production.
In Python and notebooks, keep one long-lived connection per process instead of reconnecting for each query. It preserves the catalog, avoids extension reloads, and keeps registered DataFrames and views visible to every subsequent query.
1bench is a native GUI for DuckDB. Inspect queries, connections, and settings without leaving the app. See what's happening before you have to Google it.
Open DuckDB in 1bench