Incident brief
Column reference is ambiguous
A query referenced a bare column name that exists in more than one table in the FROM clause, so PostgreSQL could not tell which table you meant.
What lands in your log
ERROR: column reference "id" is ambiguous
In 10 seconds
- What triggers it
- Create two tables that share a column name (here both have id and name).
- Fix
- Qualify the column with its table name or alias (employees.id, or e.id).
- Proof
- Reproduced on PostgreSQL 16.14 → Selecting the bare column id from a USING (name) join of two tables that both have an id column was rejected with SQLSTATE 42702. Qualifying the column resolved it.
Fix
What to do right now
Application-level steps for this error.
- Qualify the column with its table name or alias (employees.id, or e.id).
- If the column is a shared join key, list it in USING (...) so the join merges it into a single output column.
- Give tables short aliases and always qualify shared column names in multi-table queries.
-- qualify the column so PostgreSQL knows which table's id you mean
SELECT e.id, e.name
FROM employees e
JOIN departments d ON e.id = d.id;For this error
See this error live on the server
Run these against the affected instance to confirm the diagnosis before you act.
Column reference is ambiguous is fixed in the statement text. PostgreSQL stores no failed parse tree, so use the error POSITION against the exact SQL sent by the driver and inspect real column/function names.
Candidate columns on the referenced relations
Replace the relation array with the tables/aliases in the failing statement.
SELECT attrelid::regclass AS table_name, attnum, attname,
format_type(atttypid, atttypmod) AS data_type
FROM pg_attribute
WHERE attrelid = ANY (ARRAY[
to_regclass('<first_relation>'),
to_regclass('<second_relation>')
]::regclass[])
AND attnum > 0 AND NOT attisdropped
ORDER BY attname, table_name;Why it happens
What PostgreSQL is telling you
The mechanism behind the error, grounded in the official manual, not paraphrased.
PostgreSQL 16 Documentation, §7.2.1.1 Joined Tables
While JOIN ON produces all columns from T1 followed by all columns from T2, JOIN USING produces one output column for each of the listed column pairs (in the listed order), followed by any remaining columns from T1, followed by any remaining columns from T2.Read the full section on postgresql.org →
The ambiguous, unqualified reference
USING (name) only merges the name column. Both employees and departments still expose their own id, so the bare reference id is ambiguous and PostgreSQL raises SQLSTATE 42702 instead of guessing.The session is unaffected by the parse error
42702 is a parse-time error, so nothing ran. The connection is fine and the next statement returns normally.Reproduce & verify
A real, single-session PostgreSQL reproduction
A literal transcript of SQL run against a live PostgreSQL instance in an isolated lab. The commands below are exactly what was executed.
- 1Create two tables that share a column name (here both have id and name).
- 2Join them with USING (name) so only name is merged, id still exists on both sides.
- 3Select the bare column id without qualifying it with a table name or alias.
- 4PostgreSQL rejects the statement with SQLSTATE 42702 because id is present in both tables.
One client: two tables that both have id and name, joined with USING (name) so id remains on both sides.
CREATE TABLE employees (id int, name text);
CREATE TABLE departments (id int, name text);
INSERT INTO employees VALUES (1, 'Ada');
INSERT INTO departments VALUES (1, 'Engineering');SELECT id FROM employees JOIN departments USING (name);SELECT 'ok' AS session_after_error;What PostgreSQL actually returned
CREATE TABLE
CREATE TABLE
INSERT 0 1
INSERT 0 1ERROR: column reference "id" is ambiguous
LINE 1: SELECT id FROM employees JOIN departments USING (name);
^ session_after_error
---------------------
ok
(1 row)Qualifying the column with a table alias was tested against the same two-table join and returned the row cleanly, proving the ambiguity, not the data, was the problem.
Without this
Above: the bare id reference raises SQLSTATE 42702.
With this, tested
Below: the qualified e.id reference returns the row.
- A second operational test: exact SQL, raw output, measured result, and engineer notes
Card required. Cancel before day 7 and you are not charged.
Connected
Everything this error touches
Every page this SQLSTATE connects to: the concept that explains it, the runbooks that fix it, the parameters you tune to prevent it, and the sibling errors it travels with. All real cross-references. Jump straight in, or open the full interactive map.
Understand the concept
Related errors
Verification
- Last verified
- 2026-07-19 (isolated lab, PostgreSQL 16.14)
- Verification scope
- Verified against PostgreSQL 16.14 in an isolated lab environment
- Audit status
- reviewed
Went further?
Pro unlocks the second lab proof
Free page stops the bleeding. Pro adds the operational test, SQLSTATE audit, and deeper evidence, same error, more certainty.