Skip to content
PostgreSQL

PostgreSQL Error 42601

syntax error at or near

Applies to: PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
Last technically reviewed 24 October 2026 on PostgreSQL 18.6 (PGlite 0.5.11)
The full message
ERROR:  syntax error at or near "FROM"
Other forms of this message
The statement stops too early
ERROR:  syntax error at end of input
A string literal is never closed (usually from a driver or GUI; psql waits for the closing quote instead)
ERROR:  unterminated quoted string at or near "'Sara;"
Double quotes used for an empty string
ERROR:  zero-length delimited identifier at or near """"
INSERT value list longer than the column list
ERROR:  INSERT has more expressions than target columns
INSERT column list longer than the value list
ERROR:  INSERT has more target columns than expressions
UNION, INTERSECT or EXCEPT branches with different column counts
ERROR:  each UNION query must have the same number of columns
How psql adds the position (reconstructed from the error position the server reports)
LINE 1: SELECT id, name, FROM customers;
                         ^
SQLSTATE
42601
Condition name
syntax_error
Product
PostgreSQL
Versions
PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
Last reviewed
24 October 2026

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;
What to look for

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;
What to look for

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;
What to look for

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 side

Find 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-only

Use 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 schema

Prefer 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 side

A 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 data

For 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;
Result
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;
Result
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);
Result
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');
Result
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

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.

Still stuck on a PostgreSQL error?

Browse the full PostgreSQL error library, or get hands-on help from an experienced SQL professional.