PostgreSQL Error 42611: invalid column definition
PostgreSQL error code 42611 (invalid_column_definition) occurs when a column definition in a CREATE TABLE, ALTER TABLE, or similar DDL statement contains syntax or options that PostgreSQL cannot accept. This typically happens due to incorrect ordering of constraints, invalid type precision, or misuse of advanced column features like IDENTITY or generated columns. The entire statement is rejected and rolled back the moment the parser detects the invalid definition.
Top 3 Causes
1. Incorrect Constraint Ordering or Missing Parentheses
PostgreSQL expects column definitions to follow a strict order: name → type → DEFAULT → constraints. Placing constraints in the wrong order or forgetting parentheses around CHECK expressions is a very common mistake.
-- ❌ Error: CHECK missing parentheses, wrong order
CREATE TABLE orders (
status VARCHAR(20) CHECK status IN ('open','closed') DEFAULT 'open'
);
-- ✅ Correct
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
status VARCHAR(20) DEFAULT 'open' CHECK (status IN ('open', 'closed')),
amount NUMERIC(12,2) NOT NULL DEFAULT 0.00
);
2. Invalid Data Type Precision or Length
Types like NUMERIC(p, s), VARCHAR(n), and CHAR(n) require valid positive integers within allowed ranges. Using zero, negative numbers, or out-of-range values triggers error 42611.
-- ❌ Error: negative precision, zero length
CREATE TABLE products (
price NUMERIC(-1, 2),
name VARCHAR(0)
);
-- ✅ Correct
CREATE TABLE products (
product_id SERIAL PRIMARY KEY,
price NUMERIC(12, 2) NOT NULL DEFAULT 0.00,
name VARCHAR(255) NOT NULL
);
3. Misuse of IDENTITY or Generated Columns
GENERATED ALWAYS AS IDENTITY (PostgreSQL 10+) cannot be mixed with a DEFAULT clause. Generated columns (PostgreSQL 12+) require the STORED keyword and an integer-compatible base type for IDENTITY.
-- ❌ Error: IDENTITY mixed with DEFAULT, missing STORED
CREATE TABLE employees (
emp_id INT GENERATED ALWAYS AS IDENTITY DEFAULT 1,
annual_sal NUMERIC(12,2),
monthly_sal NUMERIC GENERATED ALWAYS AS (annual_sal / 12)
);
-- ✅ Correct
CREATE TABLE employees (
emp_id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
annual_sal NUMERIC(12, 2) NOT NULL DEFAULT 0.00,
monthly_sal NUMERIC(12, 2) GENERATED ALWAYS AS (annual_sal / 12) STORED
);
Quick Fix Solutions
-
Check column definition order: Always follow
column_name → data_type → DEFAULT → NOT NULL/CHECK/UNIQUE. -
Wrap CHECK expressions in parentheses:
CHECK (column > 0)notCHECK column > 0. -
Never mix IDENTITY with DEFAULT: Remove the
DEFAULTclause entirely when usingGENERATED AS IDENTITY. -
Always add STORED for generated columns: PostgreSQL does not support virtual generated columns —
STOREDis mandatory. -
Validate precision ranges:
NUMERICprecision must be between 1 and 1000;VARCHAR/CHARlength must be ≥ 1.
-- Safe ALTER TABLE pattern for adding a NOT NULL column to a populated table
ALTER TABLE customers ADD COLUMN phone VARCHAR(20);
UPDATE customers SET phone = 'N/A' WHERE phone IS NULL;
ALTER TABLE customers ALTER COLUMN phone SET NOT NULL;
Prevention Tips
Adopt a standard column definition template across your team and validate all DDL scripts in a development or staging environment before applying them to production. Integrate a linter or
psqlsyntax check into your CI/CD pipeline.Query
information_schema.columnsbefore altering tables to understand existing column definitions, and always verify your PostgreSQL version supports the features you intend to use (IDENTITYrequires v10+, generated columns require v12+).
-- Check PostgreSQL version
SELECT current_setting('server_version_num')::INT;
-- Inspect existing column definitions
SELECT column_name, data_type, is_nullable,
column_default, is_generated, generation_expression
FROM information_schema.columns
WHERE table_name = 'your_table'
ORDER BY ordinal_position;
Related Errors
-
42601
syntax_error— Broader SQL syntax error, often appearing alongside 42611 for badly malformed DDL. -
42P16
invalid_table_definition— Table-level definition errors such as duplicate primary keys or invalid partition structures. -
42804
datatype_mismatch— Type incompatibility, commonly seen duringALTER COLUMN ... TYPEoperations. -
0A000
feature_not_supported— Triggered when using features unavailable in the current PostgreSQL version, easily confused with 42611.
📖 Want a more detailed guide?
Check out the full in-depth version (Korean) on oraerror.com — includes detailed analysis, additional SQL examples, and prevention tips.
Top comments (0)