42P18
PostgreSQLERRORCommonIndeterminate DatatypeHIGH confidence

could not determine data type of parameter $N

What this means

The query parser was unable to infer the type of a parameter placeholder ($1, $2, etc.) or an untyped literal because there is insufficient context in the query to determine what type to use.

Why it happens
  1. 1Using a parameter placeholder ($1) in a position where the type cannot be inferred from surrounding context
  2. 2Passing an untyped NULL without a cast in a UNION or CASE expression
  3. 3Prepared statements where the parameter appears only in a VALUES list without a column type context
  4. 4Using $1 in a standalone SELECT without comparison or assignment context
How to reproduce

A prepared statement parameter has no type context for inference.

trigger — this will error
trigger — this will error
PREPARE test_stmt AS SELECT $1;
EXECUTE test_stmt('hello');

expected output

ERROR:  could not determine data type of parameter $1

Fix 1

Add an explicit type cast to the parameter

WHEN When you know the expected type of the parameter.

Add an explicit type cast to the parameter
PREPARE test_stmt AS SELECT $1::TEXT;
EXECUTE test_stmt('hello');

-- In application code (e.g. node-postgres):
-- const res = await client.query('SELECT $1::text', ['hello']);

Why this works

The parser infers parameter types by examining the expression context (e.g., a comparison with a typed column). When no context exists, an explicit cast (::TEXT, ::INTEGER) supplies the type directly, allowing the parser to record the type in the parameter descriptor.

Fix 2

Provide a type context through comparison or assignment

WHEN When the parameter is used in a query with a typed column.

Provide a type context through comparison or assignment
PREPARE find_user AS SELECT * FROM users WHERE email = $1;
EXECUTE find_user('alice@example.com');
-- email is TEXT, so $1 is inferred as TEXT

Why this works

The parser walks the expression tree and uses type unification to propagate known types to adjacent parameters. A comparison with a typed column (email TEXT) tells the parser that $1 must also be TEXT, resolving the indeterminate type.

What not to do

✕ Use string interpolation to embed values directly in SQL strings

Bypasses the parameterised query mechanism and opens the code to SQL injection vulnerabilities.

Sources
Official documentation ↗

src/backend/parser/parse_param.c — transformParamRef()

PREPARE ↗

Content generated with AI assistance and reviewed for accuracy. Found an error? hello@errcodes.dev

← All PostgreSQL errors