- Result code
- SQLITE_ERROR (1)
- Product
- SQLite library
- Versions
- SQLite 3.x (examples run on 3.39.2; shell output from 3.50.6)
- Category
- Missing & Duplicate Objects
- Last reviewed
- 24 October 2026
On this page
What it means
The statement names a table that does not exist in the database file this connection opened. Most often the table is fine but the program opened a different, often brand-new and empty, file.
SQLite looks the name up in the schema of the databases the connection has open: main (the file you opened), temp (this connection's temporary tables) and any attached databases. If no table or view has that name, the statement is rejected while it is being prepared, before anything runs. The error is raised for the whole statement, so in a script the statements before it have already run.
The most confusing case is a wrong path. When a program opens a file that does not exist, SQLite normally creates it: in the lab, opening a misspelt path created a 0-byte file and the first query failed with "no such table". Relative paths make this common, because they are resolved from the process's current directory, which differs between your IDE, a web server, a service and a scheduled task. So check which file is open before you look for the table.
Names are not case-sensitive for ASCII letters (CUSTOMERS finds customers; checked on 3.39.2), so case is rarely the cause, but a name containing a non-ASCII letter must match that letter's case exactly. A name with a space or a reserved word must be quoted ("order items"). The error names the schema when the statement did, for example archive.orders, and it reads main.order_log when it comes from a view, trigger or foreign key. Dropping a missing index or view gives the separate messages no such index: ... and no such view: ....
Common causes
- The program opened a different file than you think: a typo or a relative path resolved from another working directory, so SQLite created a new empty database.
- The table was never created on this copy of the database: a migration or setup script did not run, failed half way, or ran against another file.
- The table is in another database file that this connection has not attached, or the statement uses the wrong schema name.
- The table is a TEMP table created on another connection; temporary tables exist only for the connection that created them (connection pools hand you a different one).
- A view, trigger or foreign key still refers to a table that was dropped or renamed.
- A typo in the name, or a name with spaces or a reserved word that needs quoting.
Diagnose it
Read-only These statements only read the schema (sqlite_schema and read-only PRAGMA queries) or your own data. They do not change data, settings or the database file, so they are safe to run first.
Which file is this connection using?
Run this from the same program (or log its output), not from a separate tool that may open a different file.
PRAGMA database_list; One row per open database: main with the full path of the file, temp, and any attached databases. If the path is not the file you meant, or the file is unexpectedly small (0 bytes for a new empty file), fix the path rather than the schema.
List the tables and views in every attached database
PRAGMA table_list; -- SQLite 3.37.0 and later Every table and view with its schema (main, temp or an attached name) and type. Only sqlite_schema and sqlite_temp_schema means the file is empty.
Search the schema for a similar name
SELECT type, name, tbl_name
FROM sqlite_schema
WHERE name LIKE '%custom%' -- part of the name you expect
ORDER BY name; Tables, views, indexes and triggers whose name contains the text, which shows spelling differences such as customer and customers. Older versions name this table sqlite_master, and every version still accepts that name. Temporary tables are listed in sqlite_temp_schema.
Has the migration run on this file?
PRAGMA user_version; The schema version number stored in the file. Many migration tools record their version here or in their own table; compare it with the version your code expects. 0 on a database that should be migrated suggests the migrations never ran on this file.
How to fix it
Each fix is labelled with what it changes. Try read-only checks and the least invasive fix first, and test changes outside production.
Open the right file, with an absolute path
Client or network sideBuild the path from a known location instead of the current directory, and, where the file must already exist, open it without the create flag so a wrong path fails at once with unable to open database file instead of creating an empty database. In PHP PDO (checked here with PHP 8.2):
Caution: Delete the empty database files that a wrong path created only after checking they are 0 bytes or contain no tables, so you do not remove a real database by mistake.
$db = new PDO('sqlite:' . __DIR__ . '/data/shop.db', null, null, [
PDO::SQLITE_ATTR_OPEN_FLAGS => PDO::SQLITE_OPEN_READWRITE, // no SQLITE_OPEN_CREATE
]);
Create the table or run the missing migration
Changes schemaIf the file is right but the table is missing, run the migration or setup script against this file and check that it completed. For tables created at start-up, IF NOT EXISTS makes the script safe to run again.
CREATE TABLE IF NOT EXISTS customers (
id INTEGER PRIMARY KEY,
email TEXT UNIQUE
);
Attach the other database and name its schema
Changes database stateA table in another file needs that file attached to this connection, and the statement must use the schema name you gave it. ATTACH lasts only for the current connection.
Caution: ATTACH also creates the file if it does not exist, and a relative path is resolved from the current directory, so a wrong path gives an empty attached database and the same error. Use an absolute path.
ATTACH DATABASE '/srv/app/data/archive.db' AS archive;
SELECT * FROM archive.orders;
Use temporary tables on the connection that created them
Client or network sideCreate and use a TEMP table on one connection (keep the connection open for the whole job), or make it a normal table if other connections or later requests need it. Temporary tables are dropped when their connection closes.
CREATE TEMP TABLE cart (id INTEGER PRIMARY KEY, sku TEXT);
INSERT INTO cart (sku) VALUES ('PEN-1'); -- same connection
SELECT * FROM temp.cart;
Recreate views and triggers that name a dropped table
Changes schemaWhen the message names main.something and the statement did not, look for a view or trigger whose SQL mentions that table (SELECT name, sql FROM sqlite_schema WHERE sql LIKE '%order_log%'), then recreate the table or drop and recreate the view or trigger without it.
DROP TRIGGER IF EXISTS trg_orders_log;
CREATE TABLE IF NOT EXISTS order_log (order_id INTEGER, logged_at TEXT);
Examples
A misspelt table name
CREATE TABLE customers (id INTEGER PRIMARY KEY, email TEXT);
SELECT * FROM customer; -- the table is customers
no such table: customer
Reproduced on SQLite 3.39.2, 24 October 2026.
A wrong path opens a new, empty database
Lab: the connection opened a path where no database existed. SQLite created a 0-byte file there and the first query failed. The same happens when a relative path is resolved from another working directory.
-- the program opened data/shop-new.db instead of data/shop.db
SELECT * FROM customers;
no such table: customers
Reproduced on SQLite 3.39.2, 24 October 2026.
A temporary table used from another connection
-- connection A
CREATE TEMP TABLE cart (id INTEGER PRIMARY KEY, sku TEXT);
-- connection B (for example another request from a pool)
SELECT * FROM cart;
no such table: cart
Reproduced on SQLite 3.39.2, 24 October 2026.
A trigger still writes to a table that was dropped
CREATE TABLE orders (id INTEGER PRIMARY KEY, total REAL);
CREATE TABLE order_log (order_id INTEGER);
CREATE TRIGGER trg_orders_log AFTER INSERT ON orders
BEGIN
INSERT INTO order_log (order_id) VALUES (new.id);
END;
DROP TABLE order_log;
INSERT INTO orders (total) VALUES (9.99);
no such table: main.order_log
Reproduced on SQLite 3.39.2, 24 October 2026.
How to prevent it
Configure the database location as an absolute path (or build it from the application's own directory), log the path at start-up, and open existing databases without the create flag, so a wrong path is an error instead of a new empty file. Keep the database outside folders that are recreated on deploy.
Run migrations automatically at start-up and record the schema version (for example in PRAGMA user_version), so code never runs against a file that is behind. When you drop or rename a table, check sqlite_schema for views and triggers that still mention it.
Common questions
How do I fix "no such table" in SQLite?
First run PRAGMA database_list from the failing program to see which file it opened. If it is the wrong or a new empty file, fix the path (use an absolute path). If the file is right, list its tables with PRAGMA table_list or sqlite_schema and create the table or run the missing migration.
The table exists in DB Browser, so why does my program say no such table?
They are almost certainly looking at different files. A relative path in your program is resolved from its working directory, and SQLite creates a new empty file if the path does not exist. Compare the path from PRAGMA database_list in the program with the file open in the tool.
Are SQLite table names case-sensitive?
Not for ASCII letters: CUSTOMERS, Customers and customers are the same table. Letters outside ASCII are compared exactly, and names with spaces or reserved words must be quoted with double quotes.
Why does the message say main.something when my query does not use that table?
The table is referenced by a view or trigger on the table you used (or by a foreign key), and it no longer exists. Find the view or trigger in sqlite_schema and recreate the missing table or the view or trigger.
Learn more on CodeWithSQL
Official documentation
- The schema table (sqlite_schema)
- ATTACH DATABASE
- PRAGMA table_list and database_list
- URI filenames (mode=rw and other open options)
Last technically reviewed 24 October 2026; examples and diagnostics run on SQLite 3.39.2 (PHP PDO_SQLITE) and the sqlite3 shell 3.50.6. Messages are the text the SQLite library itself returns (sqlite3_errmsg) for the versions shown.