Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Rules

Every rule has a code, a name and a category. Rules in the correctness category report queries the database rejects (or that fail at run time) and are errors by default; rules in the suspicious category report valid queries that almost certainly don't do what was meant, and are warnings by default. Rules in the restriction category ban constructs some codebases don't want and are off until you enable them. See Rules and levels to change their levels and Suppressing diagnostics for exceptions.

The E in a rule code is sqlsift's prefix, not a severity: a rule's level comes from its category and your configuration, so a warning can carry an E code too. Codes are assigned in order as rules are added and never change or get reused, so they are safe to keep in config files, suppression comments and baselines. Names are easier to read in config and comments; codes are shorter.

The examples on these pages use this schema:

CREATE TYPE order_status AS ENUM ('open', 'paid', 'shipped');
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT NOT NULL UNIQUE,
  created_at TIMESTAMP NOT NULL DEFAULT now()
);
CREATE TABLE orders (
  id SERIAL PRIMARY KEY,
  user_id INTEGER NOT NULL REFERENCES users(id),
  status order_status NOT NULL DEFAULT 'open',
  total NUMERIC(10, 2) NOT NULL
);
CREATE TABLE coupons (
  code TEXT PRIMARY KEY,
  order_id INTEGER REFERENCES orders(id)
);
CodeNameDescription
E0001table-not-foundReferenced table does not exist in schema
E0002column-not-foundReferenced column does not exist in table
E0003type-mismatchType incompatibility in expression
E0004potential-null-violationPotential NOT NULL violation
E0005column-count-mismatchColumn count doesn't match (INSERT, column aliases, subqueries)
E0006ambiguous-columnColumn reference is ambiguous across tables
E0007join-type-mismatchJOIN condition compares incompatible types
E0008missing-required-columnINSERT omits a NOT NULL column without a default
E0009duplicate-nameTable alias or CTE name given twice in one query
E0010duplicate-target-columnColumn given twice in an INSERT column list or UPDATE SET
E0011position-out-of-rangeORDER BY / GROUP BY position is not in the select list
E0012misplaced-aggregateAggregate or window function where it is not allowed
E0013generated-column-writeINSERT or UPDATE gives a value to a generated column
E0014unmatched-conflict-targetON CONFLICT columns match no unique constraint
E0015distinct-order-bySELECT DISTINCT ordered by a column it doesn't select
E0016grouping-errorColumn must appear in GROUP BY or be used in an aggregate
E0017value-out-of-rangeLiteral too long or out of range for the column type
E0018null-comparisonComparison with NULL using = or <> is never true
E0019not-in-with-nullsNOT IN over a nullable subquery column
E0020outer-column-in-subqueryIN subquery selects a column of the outer query
E0021missing-join-conditionTables in FROM with no condition linking them
E0022constant-conditionCondition that is always or never true from the schema
E0023outer-join-filteredWHERE condition turns an outer join into an inner join
E0024unfiltered-writeUPDATE or DELETE without WHERE
E0025insert-without-columnsINSERT without a column list
E0026select-starSELECT * in a query's result columns
E0027wrong-argument-typeFunction or operator given an argument type it doesn't take
E0028limit-without-order-byLIMIT or OFFSET without ORDER BY
E1000parse-errorSQL could not be parsed