Skip to content
PostgreSQL

PostgreSQL Error 42703

column does not exist

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:  column "firstname" does not exist
HINT:  Perhaps you meant to reference the column "customers.FirstName".
Other forms of this message
Qualified with a table or alias (no quotes around the name)
ERROR:  column c.lastname does not exist
HINT:  Perhaps you meant to reference the column "c.last_name".
Target column of an INSERT or UPDATE
ERROR:  column "bonus" of relation "customers" does not exist
UPDATE ... SET qualified with the table name
ERROR:  column "customers" of relation "customers" does not exist
HINT:  SET target columns cannot be qualified with the relation name.
No close match, so no HINT
ERROR:  column "annual" does not exist
How psql adds the position (reconstructed from the error position the server reports)
LINE 1: SELECT firstname FROM customers;
               ^
SQLSTATE
42703
Condition name
undefined_column
Product
PostgreSQL
Versions
PostgreSQL 13 to 18 (examples run on PostgreSQL 18.6 in PGlite)
Last reviewed
24 October 2026

What it means

SQLSTATE 42703 means a column name in the statement does not match any column of the tables in scope, usually because of case, a typo, a string written in double quotes, or an alias used where it is not visible.

PostgreSQL resolves every column name against the tables in the FROM clause (and, for INSERT and UPDATE targets, against the target table). If none has it, the statement fails with 42703 (undefined_column). Names follow the same rules as table names: unquoted names are folded to lower case, so a column created as "FirstName" is only found as "FirstName", and the message shows the folded name, firstname. When a column with a similar name exists, PostgreSQL adds a HINT such as Perhaps you meant to reference the column "customers.FirstName"., which usually is the answer.

Two other causes are easy to miss. Double quotes mark identifiers, so WHERE name = "Bob" looks for a column called Bob; strings take single quotes. And an output alias from the SELECT list can be used in ORDER BY and GROUP BY but not in WHERE or HAVING: WHERE annual > 1000 fails even though salary * 12 AS annual is in the same query. SQL Server functions written with bare date parts, such as dateadd(day, 1, now()), also fail here first, because day is read as a column name.

Common causes

  • The column was created with a quoted mixed-case name ("FirstName") and is referenced unquoted.
  • A typo, or a name from another environment or an old version of the schema (a migration that adds the column has not run).
  • A string value written in double quotes instead of single quotes, so it is read as a column name.
  • An output alias used in WHERE or HAVING, where it is not visible yet.
  • The column belongs to a different table than the one the alias points at, or the right table is missing from FROM.
  • INSERT or UPDATE names a column that the target table does not have, or UPDATE ... SET qualifies the column with the table name.
  • SQL Server or MySQL functions with bare keywords such as day or month (dateadd, datediff), which PostgreSQL reads as column names.

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.

List the real column names, with exact case

SELECT column_name, data_type
FROM information_schema.columns
WHERE table_schema = 'public'
  AND table_name = 'customers'
ORDER BY ordinal_position;
What to look for

Every column as stored. A name with capital letters (FirstName) must be quoted exactly in queries; all lower case names need no quotes.

Which tables have a column with this name?

Useful when the alias points at the wrong table or the column lives in a table you have not joined.

SELECT table_schema, table_name, column_name
FROM information_schema.columns
WHERE lower(column_name) = lower('firstname')
  AND table_schema NOT IN ('pg_catalog', 'information_schema')
ORDER BY 1, 2;
What to look for

Each table that has the column, in any case. No rows means the column does not exist in this database, perhaps because a migration has not run.

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.

Use the exact name, or rename the column to lower case

Changes schema

Follow the HINT and quote the mixed-case name exactly. To stop the problem for good, rename the column to lower case once and update queries that quote the old name.

SELECT "FirstName" FROM customers;

-- or rename it once
ALTER TABLE customers RENAME COLUMN "FirstName" TO first_name;

Put string values in single quotes

Read-only

Single quotes make a string; double quotes make a name. Better still, pass values as query parameters.

SELECT * FROM customers WHERE last_name = 'Bob';

Repeat the expression, or filter in an outer query, instead of using the alias

Read-only

WHERE cannot see SELECT aliases. Repeat the expression, or compute it in a subquery or CTE and filter outside, where the alias is a real column.

SELECT salary * 12 AS annual
FROM customers
WHERE salary * 12 > 1000;

-- or
SELECT *
FROM (SELECT id, salary * 12 AS annual FROM customers) AS t
WHERE annual > 1000;

Write date arithmetic the PostgreSQL way

Read-only

PostgreSQL has no dateadd or datediff; add or subtract an interval, and use date_part or age for differences.

SELECT now() + interval '1 day' AS tomorrow;

Add the column if it is genuinely missing

Changes schema

If the column should exist (code was deployed before its migration), run the migration. For UPDATE, write the target column unqualified: UPDATE customers SET salary = 5.

ALTER TABLE customers ADD COLUMN bonus numeric;

Examples

A quoted mixed-case column referenced without quotes

CREATE TABLE customers (id int, "FirstName" text, last_name text);

SELECT FirstName FROM customers;
Result
ERROR:  column "firstname" does not exist
HINT:  Perhaps you meant to reference the column "customers.FirstName".

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

A string value in double quotes

CREATE TABLE customers (id int, first_name text, last_name text);

SELECT * FROM customers WHERE last_name = "Bob";
Result
ERROR:  column "Bob" does not exist

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

A SELECT alias used in WHERE

CREATE TABLE customers (id int, salary numeric);

SELECT salary * 12 AS annual
FROM customers
WHERE annual > 1000;
Result
ERROR:  column "annual" does not exist

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

Inserting into a column the table does not have

CREATE TABLE customers (id int, salary numeric);

INSERT INTO customers (id, bonus) VALUES (1, 5);
Result
ERROR:  column "bonus" of relation "customers" does not exist

Reproduced on PGlite 0.5.11 (PostgreSQL 18.6 compiled to WebAssembly), 24 October 2026.

How to prevent it

Use lower case names with underscores for every column and never quote them, and turn off identifier quoting in ORMs and GUI tools that create tables. Keep application code and migrations in step, so code that reads a new column is deployed only after the migration that adds it.

Always use single quotes for strings, or better, parameters. Qualify columns with table aliases in multi-table queries, which also prevents 42702 ambiguous column errors.

Common questions

Why does PostgreSQL say column does not exist when I can see it?

Most often the column was created with capital letters inside double quotes, so it must be written the same way ("FirstName"); unquoted names are folded to lower case. Read the HINT line, which often names the column you meant.

Why is my string treated as a column name?

In PostgreSQL double quotes mark identifiers. Write string values in single quotes: WHERE status = 'active'.

Can I use a column alias in WHERE in PostgreSQL?

No. WHERE is evaluated before the SELECT list, so the alias does not exist yet; the same applies to HAVING. Repeat the expression or filter in an outer query. ORDER BY and GROUP BY can use output aliases.

Why does dateadd(day, ...) give column "day" does not exist?

dateadd is a SQL Server function. PostgreSQL first fails on the bare word day, which it reads as a column. Use interval arithmetic instead, for example now() + interval '1 day'.

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.