- SQLSTATE
- 42601
- Condition name
syntax_error- Product
- PostgreSQL
- Versions
- PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
- Category
- Syntax & Names
- Last reviewed
- 24 October 2026
On this page
What it means
SQLSTATE 42601 means PostgreSQL could not parse the statement: a word, symbol or the end of the text appeared where the grammar does not allow it, so nothing was run.
PostgreSQL parses the whole statement before running any of it. When the parser meets a token that cannot come next, it stops and reports that token: syntax error at or near "FROM" means the problem is at, or just before, the word FROM. psql adds a LINE line with a caret under that spot, and drivers return the same information as a character position. The real mistake is often one token earlier: a trailing comma before FROM, a missing comma between columns, an unclosed bracket. "syntax error at end of input" means the statement ended while the parser still expected more, such as a WHERE with no condition.
The most common source is SQL written for another database. SQL Server TOP and [brackets], MySQL backtick quoting and UPDATE ... LIMIT are not PostgreSQL syntax. Reserved words such as user, order and limit cannot be used as bare table or column names. A few checks that are not strictly grammar also use 42601, such as an INSERT whose column and value lists have different lengths, and UNION branches with different column counts. Because nothing ran, no data changed, but inside a transaction the error still aborts it (25P02).
Common causes
- A trailing comma before FROM or a closing bracket, or a missing comma between two columns.
- Syntax from another database: TOP n and [name] from SQL Server, `name` backticks and UPDATE or DELETE ... LIMIT from MySQL.
- A reserved word such as user, order, group or limit used as an unquoted table or column name.
- A string that contains an apostrophe (O'Brien) built into the SQL text without doubling the quote, which also opens the door to SQL injection.
- Double quotes used around a string value: "" is an empty identifier and "text" is a column name, not a string.
- A statement cut short or glued together by the application: an empty IN (), a dangling WHERE or AND, or a missing semicolon between two statements.
- Syntax that needs a newer PostgreSQL version than the server you are connected to.
Diagnose it
Read-only These queries only read the system catalogs (pg_catalog, information_schema) and statistics views such as pg_stat_activity and pg_locks. They do not change data, roles or settings, so they are safe to run first.
Is the word a reserved keyword?
When the error points at a name you chose, check whether PostgreSQL treats it as a keyword.
SELECT word, catcode, catdesc
FROM pg_get_keywords()
WHERE word IN ('user', 'order', 'limit', 'name')
ORDER BY word; catcode R (reserved) words cannot be bare table or column names: quote them or choose another name. U (unreserved) words such as name are allowed.
Which PostgreSQL version is the server?
Syntax copied from current documentation may not exist on an older server.
SELECT version();
SELECT current_setting('server_version_num') AS version_num; The server version, for example 180006 for 18.6. Compare it with the version of the documentation page you copied the syntax from; postgresql.org shows a version switcher on every page.
Parse a query without running it
Plain EXPLAIN parses and plans a SELECT without executing it, so a syntax error appears exactly as it would at run time, and a corrected query shows its plan.
EXPLAIN
SELECT id, name
FROM customers
ORDER BY name
LIMIT 5; A query plan means the statement parses. A 42601 error shows the same token as the original failure.
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.
Look at the token in the message and the one before it
Client or network sideFind the caret (psql) or the position (drivers) and read backwards: a comma before FROM, a missing comma, an unclosed bracket or quote. If the SQL is built in code, print the final statement text; the error is in what was sent, not in the template you wrote.
Translate SQL Server and MySQL syntax
Read-onlyUse LIMIT (or FETCH FIRST n ROWS ONLY) instead of TOP, double quotes instead of [brackets] or backticks, COALESCE instead of ISNULL, and a subquery on the key instead of UPDATE ... LIMIT. The SQL Server to PostgreSQL guide lists more.
-- SQL Server: SELECT TOP 5 [name] FROM customers ORDER BY name;
SELECT "name" FROM customers ORDER BY name LIMIT 5;
-- the standard form also works
SELECT name FROM customers ORDER BY name FETCH FIRST 5 ROWS ONLY;
Rename (or quote) identifiers that are reserved words
Changes schemaPrefer a name that is not a keyword, such as app_user instead of user. Quoting with double quotes works, but then every query must quote it, and an unquoted SELECT * FROM user silently returns the current role name instead of your table.
CREATE TABLE app_user (id int PRIMARY KEY, name text);
-- possible, but every query must then write "user"
CREATE TABLE "user" (id int PRIMARY KEY, name text);
Pass values as parameters instead of building them into the SQL
Client or network sideA value such as O'Brien breaks a hand-built string literal and is how SQL injection happens. Use your driver's placeholders ($1 in PostgreSQL drivers, ? or :name in many libraries). In hand-written SQL, double the apostrophe: 'O''Brien', or use dollar quoting.
-- hand-written SQL
SELECT * FROM customers WHERE name = 'O''Brien';
Make column and value lists the same length
Changes dataFor the INSERT and UNION forms, count both sides. Name the target columns explicitly so a later schema change cannot shift values into the wrong column.
INSERT INTO customers (id, name, email)
VALUES (1, 'Sara', 'sara@example.com');
Examples
A trailing comma before FROM
The mistake is the comma after name, but PostgreSQL reports the next token, FROM, because a comma there could still have been followed by another column.
CREATE TABLE customers (id int, name text, email text);
SELECT id, name, FROM customers;
ERROR: syntax error at or near "FROM"
Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.
SQL Server TOP in PostgreSQL
PostgreSQL reads TOP as a column name and then cannot place 5. The fix is SELECT * FROM customers LIMIT 5;. Square brackets fail the same way: SELECT [name] FROM customers gives syntax error at or near "[".
CREATE TABLE customers (id int, name text, email text);
SELECT TOP 5 * FROM customers;
ERROR: syntax error at or near "5"
Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.
A reserved word as a table name
CREATE TABLE user (id int, name text);
ERROR: syntax error at or near "user"
Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.
More values than columns in an INSERT
CREATE TABLE customers (id int, name text, email text);
INSERT INTO customers (id, name) VALUES (1, 'Sara', 'sara@example.com');
ERROR: INSERT has more expressions than target columns
Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.
How to prevent it
Use parameters for every value from users or files, which avoids broken quoting and SQL injection together. Name tables and columns in lower case with underscores and avoid keywords, so nothing needs quoting. Format long statements one clause per line: the LINE number in the error then points straight at the clause.
When porting SQL from SQL Server or MySQL, test it against PostgreSQL (the PostgreSQL playground runs it in the browser) and use a formatter or linter that understands the PostgreSQL dialect. Check the server version before using syntax from the current documentation.
Common questions
How do I find where a PostgreSQL syntax error is?
Use the token in quotes and the position: psql prints a LINE line with a caret, and drivers return the character position. The mistake is at that token or just before it, often a missing or extra comma.
What does "syntax error at end of input" mean?
The statement ended while PostgreSQL still expected more, for example a WHERE with no condition, an unclosed bracket, or SQL cut off by the application. Print the exact text that was sent.
Why does SELECT TOP work in SQL Server but not in PostgreSQL?
TOP is SQL Server syntax. PostgreSQL uses LIMIT n, or the standard FETCH FIRST n ROWS ONLY, at the end of the query.
Why do I get "zero-length delimited identifier"?
Double quotes in PostgreSQL mark identifiers (table and column names), not strings, so "" is an empty name. Use single quotes for string values: WHERE name = ''.
Learn more on CodeWithSQL
Official documentation
- PostgreSQL error codes (Appendix A)
- SQL syntax: lexical structure (identifiers, quoting, constants)
- SQL key words (Appendix C)
- SELECT (LIMIT and FETCH)
Last technically reviewed 24 October 2026; examples and diagnostics run on PostgreSQL 18.6 (PGlite 0.5.11). SQL-level examples were run in PGlite (PostgreSQL compiled to WebAssembly); examples that need a running server are shown as documented in the PostgreSQL documentation.