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