InletDownload

PostgreSQL error 42601

syntax error at or near

PostgreSQL couldn’t parse the statement, and the quoted word is where it gave up. The mistake is usually just before that point: a reserved word used as a name, a missing or extra comma, MySQL-only syntax, or a quote or bracket that isn’t closed.

ERROR:  syntax error at or near "user"

Tested on PostgreSQL 18.6 (also 14–17) · Updated 9 October 2026

What it means

The parser read your statement word by word and reached one that can’t come next. That word is in the message, and the caret under LINE 1 points at it:

ERROR:  syntax error at or near "email"
LINE 1: SELECT id name email FROM customers;
                       ^

The real mistake is often a word or two before the caret. Here the commas are missing: PostgreSQL read id name as “id, renamed to name”, so email was the first word that made no sense. syntax error at end of input means the statement stopped early: a clause or bracket was left unfinished.

Nothing ran; a syntax error is caught before the statement starts.

Common causes

  1. A reserved word used as a name. user, order, group, limit, desc, table and others can’t be table or column names unless you quote them.
  2. A missing comma between columns, so two names run together.
  3. A trailing comma before FROM, WHERE or a closing bracket, often after deleting the last column of a list.
  4. MySQL syntax: backticks around names, AUTO_INCREMENT, LIMIT 10, 20, ON DUPLICATE KEY UPDATE.
  5. An unbalanced quote or bracket: 'O'Brien', count(*.
  6. Clauses in the wrong order: ORDER BY before WHERE, LIMIT before ORDER BY.
  7. Generated SQL with a hole in it: an empty IN () list, WHERE with nothing after it, a dangling AND, or a table name passed as a $1 parameter.

How to fix it

Quote reserved words, or rename

CREATE TABLE "user" (id int PRIMARY KEY, name text);
SELECT id, "desc" FROM products;

Once a name needs quotes, it needs them everywhere, so renaming (app_user, orders, description) is usually less trouble. Watch out for user in particular: SELECT * FROM user doesn’t fail. It returns the name of the current role, because user is a built-in that means current_user; the table is "user".

Check the commas

Every item in a select list, column list or VALUES list is separated by a comma, and the last one has none:

SELECT id, name, email FROM customers;
CREATE TABLE notes (id int PRIMARY KEY, body text);
UPDATE customers SET name = 'x' WHERE id = 1;

Translate MySQL syntax

MySQLPostgreSQL
`name`"name" (or no quotes)
id int AUTO_INCREMENT PRIMARY KEYid int GENERATED BY DEFAULT AS IDENTITY PRIMARY KEY
LIMIT 10, 20LIMIT 20 OFFSET 10
ON DUPLICATE KEY UPDATE name = 'Ada'ON CONFLICT (id) DO UPDATE SET name = 'Ada'
"text" for a string'text'

PostgreSQL recognises LIMIT 10, 20 and says so with a hint. Double-quoted strings aren’t a syntax error but a different one: column does not exist. For upserts, see duplicate key value.

Close quotes and brackets

Inside a string, write an apostrophe twice, or use dollar quoting:

SELECT * FROM customers WHERE name = 'O''Brien';
SELECT * FROM customers WHERE name = $$O'Brien$$;

In application code, pass values as parameters instead of building the string; then quotes inside values can’t break the SQL. In psql, an unclosed quote or bracket makes it wait for more input instead of running anything: the prompt changes from app=> to app'> or app(>.

Put clauses in order

SELECT … FROM … WHERE … GROUP BY … HAVING … ORDER BY … LIMIT … OFFSET.

Guard generated SQL

Parameters can carry values, never table or column names; $1 in place of a name is a syntax error. For a list that may be empty, use = ANY($1) with an array parameter: an empty array matches nothing, where IN () doesn’t parse.

Reproduce it

On PostgreSQL 18.6:

CREATE TABLE user (id int PRIMARY KEY, name text);
ERROR:  syntax error at or near "user"
LINE 1: CREATE TABLE user (id int PRIMARY KEY, name text);
                     ^

CREATE TABLE "user" (…) works, and then SELECT * FROM user; returns one row, inlet, the current role. Commas:

ERROR:  syntax error at or near "FROM"
LINE 1: SELECT id, name, FROM customers;
                         ^

ERROR:  syntax error at or near ")"
LINE 1: CREATE TABLE notes (id int PRIMARY KEY, body text,);
                                                          ^

MySQL syntax. A backtick is an operator character in PostgreSQL, so the parser only gives up at the next word:

ERROR:  syntax error at or near "FROM"
LINE 1: SELECT `name` FROM customers;
                      ^

ERROR:  syntax error at or near "AUTO_INCREMENT"
LINE 1: CREATE TABLE things (id int AUTO_INCREMENT PRIMARY KEY);
                                    ^

ERROR:  LIMIT #,# syntax is not supported
LINE 1: SELECT * FROM customers LIMIT 10, 20;
                                ^
HINT:  Use separate LIMIT and OFFSET clauses.

ERROR:  syntax error at or near "DUPLICATE"
LINE 1: ...RT INTO customers (id, name) VALUES (1, 'Ada') ON DUPLICATE ...
                                                             ^

Quotes, brackets and generated SQL:

ERROR:  syntax error at or near "Brien"
LINE 1: SELECT * FROM customers WHERE name = 'O'Brien';
                                                ^

ERROR:  syntax error at end of input
LINE 1: SELECT count(*
                      ^

ERROR:  unterminated quoted string at or near "'abc"
LINE 1: SELECT 'abc
               ^

ERROR:  syntax error at or near ")"
LINE 1: SELECT * FROM customers WHERE id IN ();
                                             ^

ERROR:  syntax error at or near "$1"
LINE 1: PREPARE p(text) AS SELECT * FROM $1;
                                         ^

PostgreSQL 14, 15, 16 and 17 print the same messages at the same positions.

In Inlet

Inlet shows the error at the position the server reports, with a hint for common ones, and ⌘↩ runs only the statement under the cursor, so you can check one statement at a time. With your own Anthropic API key, Ask Claude (⌘L) can fix the failed statement; it sends the schema, the SQL and the error, never rows.

Related

Sources