- Result code
- SQLITE_CONSTRAINT (19); extended SQLITE_CONSTRAINT_NOTNULL (1299)
- Product
- SQLite library
- Versions
- SQLite 3.x (examples run on 3.39.2; shell output from 3.50.6)
- Category
- Constraint Violations
- Last reviewed
- 24 October 2026
On this page
What it means
This error means an INSERT or UPDATE would store NULL in a column declared NOT NULL, so SQLite rejected the statement and named the table and column.
A column declared NOT NULL must always hold a value. When a statement would leave it NULL, SQLite stops the statement and reports the first column that failed as table.column. This happens in three ways: the column is left out of an INSERT and has no DEFAULT, the statement passes NULL explicitly (often an unset variable in the application), or an expression such as a subquery or a LEFT JOIN produces NULL.
A DEFAULT only applies when the column is left out of the INSERT. Writing NULL for that column, even through a parameter, still fails, because NULL is a value you supplied, not a missing one. Most drivers show only the primary code 19 (SQLITE_CONSTRAINT), shared with UNIQUE constraint failed and FOREIGN KEY constraint failed; the extended code 1299 (SQLITE_CONSTRAINT_NOTNULL) identifies this one. In SQLite a PRIMARY KEY does not imply NOT NULL (an historical quirk), except for INTEGER PRIMARY KEY, STRICT and WITHOUT ROWID tables, so a text key can silently accept NULL unless you declare it NOT NULL.
Common causes
- A required column is missing from the INSERT column list and has no DEFAULT, for example after a new NOT NULL column was added to the table but not to the application code.
- The application binds NULL: an empty form field, an unset variable or a missing JSON key becomes NULL in the parameter.
- An UPDATE sets the column from a subquery that finds no row, which returns NULL.
- An INSERT ... SELECT copies rows from a staging table, an import or a LEFT JOIN where some values are NULL, for example while rebuilding a table to add NOT NULL.
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 columns are NOT NULL, and which have defaults?
table_info lists every column of the table with its constraints.
PRAGMA table_info(customers); One row per column. notnull = 1 marks NOT NULL columns and dflt_value shows the DEFAULT (NULL means there is none). A NOT NULL column with no default must be supplied in every INSERT.
Find the source rows that would insert NULL
Before an INSERT ... SELECT or a table rebuild, count the NULLs in the source for each column that will be NOT NULL.
SELECT COUNT(*) AS rows_total,
SUM(email IS NULL) AS email_nulls
FROM customers_import; email_nulls greater than 0 means the copy will fail on those rows. List them with WHERE email IS NULL to decide whether to fill, skip or fix them.
Read the table definition
SELECT sql
FROM sqlite_schema
WHERE type = 'table' AND name = 'customers'; The CREATE TABLE statement as stored, including NOT NULL and DEFAULT clauses. Older versions name this table sqlite_master, and every version still accepts that name.
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.
Supply the value, or leave the column out so its DEFAULT applies
Changes dataValidate required fields in the application before the write, and never bind NULL for a NOT NULL column. If the column has a DEFAULT and you have no value, omit the column from the INSERT instead of passing NULL.
INSERT INTO customers (email, name) VALUES ('ali@example.com', 'Ali'); -- status takes its DEFAULT
Replace NULLs while copying rows
Changes dataIn an INSERT ... SELECT, substitute a value with COALESCE (or IFNULL), or filter the incomplete rows out and handle them separately. Choose a substitute that is honest for your data: an empty string is not the same as an unknown email address.
INSERT INTO customers (email, name)
SELECT email, COALESCE(name, '')
FROM customers_import
WHERE email IS NOT NULL;
Fix the UPDATE so it cannot produce NULL
Changes dataA scalar subquery that finds no row returns NULL. Restrict the UPDATE to rows that have a match, or wrap the subquery in COALESCE with a fallback.
UPDATE orders
SET region = (SELECT c.region FROM customers c WHERE c.id = orders.customer_id)
WHERE EXISTS (SELECT 1 FROM customers c WHERE c.id = orders.customer_id);
Add a NOT NULL column with a default
Changes schemaALTER TABLE ADD COLUMN accepts NOT NULL only together with a non-NULL DEFAULT; without one SQLite refuses with "Cannot add a NOT NULL column with default value NULL". Existing rows get the default. SQLite cannot add NOT NULL to an existing column with ALTER TABLE: that needs the table rebuild procedure from the SQLite documentation, after the NULLs found by the diagnostic above are resolved. Take a copy of the database file first.
ALTER TABLE customers ADD COLUMN phone TEXT NOT NULL DEFAULT '';
Examples
Leaving a required column out of the INSERT
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
email TEXT NOT NULL,
name TEXT
);
INSERT INTO customers (name) VALUES ('Sara'); -- no email, and no DEFAULT
NOT NULL constraint failed: customers.email
Reproduced on SQLite 3.39.2, 24 October 2026.
Passing NULL explicitly to a column that has a DEFAULT
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
status TEXT NOT NULL DEFAULT 'new'
);
INSERT INTO orders (status) VALUES (NULL); -- the DEFAULT is not used for an explicit NULL
NOT NULL constraint failed: orders.status
Reproduced on SQLite 3.39.2, 24 October 2026.
An UPDATE whose subquery finds no row
CREATE TABLE customers (id INTEGER PRIMARY KEY, region TEXT);
CREATE TABLE orders (id INTEGER PRIMARY KEY, customer_id INTEGER, region TEXT NOT NULL DEFAULT 'unknown');
INSERT INTO customers (id, region) VALUES (1, 'north');
INSERT INTO orders (customer_id) VALUES (1), (2); -- customer 2 does not exist
UPDATE orders
SET region = (SELECT c.region FROM customers c WHERE c.id = orders.customer_id);
NOT NULL constraint failed: orders.region
Reproduced on SQLite 3.39.2, 24 October 2026.
Copying rows that contain NULL into a NOT NULL column
CREATE TABLE customers_import (email TEXT, name TEXT);
INSERT INTO customers_import VALUES ('sara@example.com', 'Sara'), (NULL, 'Ali');
CREATE TABLE customers (id INTEGER PRIMARY KEY, email TEXT NOT NULL, name TEXT);
INSERT INTO customers (email, name)
SELECT email, name FROM customers_import;
NOT NULL constraint failed: customers.email
Reproduced on SQLite 3.39.2, 24 October 2026.
How to prevent it
Validate required fields in the application and treat empty input deliberately: decide whether an empty string is acceptable or the request should be rejected, rather than letting it become NULL. Give NOT NULL columns a sensible DEFAULT where one exists (a status, a created time with DEFAULT CURRENT_TIMESTAMP) and leave those columns out of INSERTs that have no value.
Declare every PRIMARY KEY column that is not an INTEGER PRIMARY KEY as NOT NULL too (or use a STRICT table), because SQLite otherwise accepts NULL keys. Before migrations that copy data, run the NULL-count query above on the source so the copy does not fail halfway through.
Common questions
How do I fix "NOT NULL constraint failed" in SQLite?
The message names the table and column. Supply a value for that column, leave it out of the INSERT if it has a DEFAULT, or replace NULLs with COALESCE when copying rows. Check the application for unset variables or empty fields that are bound as NULL.
My column has a DEFAULT. Why do I still get the error?
A DEFAULT is used only when the column is not mentioned in the INSERT. If the statement lists the column and passes NULL, SQLite treats NULL as the value and the NOT NULL constraint rejects it. Omit the column, or pass a real value.
What do INSERT OR IGNORE and INSERT OR REPLACE do with a NOT NULL violation?
In our runs OR IGNORE skipped the row without any error, which can hide lost data. OR REPLACE replaced the NULL with the column default when the column has one, and still failed when it has none, as the ON CONFLICT documentation describes. Fixing the data is usually the better choice.
Why did a NULL primary key not raise this error?
Because of an historical oversight, a PRIMARY KEY in an ordinary SQLite table allows NULL unless you add NOT NULL. INTEGER PRIMARY KEY is the exception: SQLite assigns a rowid when you pass NULL. STRICT and WITHOUT ROWID tables reject NULL keys.
Learn more on CodeWithSQL
Official documentation
- SQLite result and error codes
- CREATE TABLE: NOT NULL, DEFAULT and PRIMARY KEY
- ON CONFLICT clause (OR IGNORE, OR REPLACE)
- Quirks: PRIMARY KEYs can contain NULLs
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.