42P18ERRORTier 1 — Safe✅ HIGH confidencecould 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
- 1Using a parameter placeholder ($1) in a position where the type cannot be inferred from surrounding context
- 2Passing an untyped NULL without a cast in a UNION or CASE expression
- 3Prepared statements where the parameter appears only in a VALUES list without a column type context
- 4Using $1 in a standalone SELECT without comparison or assignment context
How to reproduce
A prepared statement parameter has no type context for inference.
PREPARE test_stmt AS SELECT $1;
EXECUTE test_stmt('hello');Fix 1: Add an explicit type cast to the parameter
When you know the expected type of 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 the parameter is used in a query with a typed column.
PREPARE find_user AS SELECT * FROM users WHERE email = $1;
EXECUTE find_user('alice@example.com');
-- email is TEXT, so $1 is inferred as TEXTWhy 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
Why it's wrong: Bypasses the parameterised query mechanism and opens the code to SQL injection vulnerabilities.
Sources
📚 Official docs: https://www.postgresql.org/docs/current/errcodes-appendix.html
📚 Feature docs: https://www.postgresql.org/docs/current/sql-prepare.html
🔧 Source ref: src/backend/parser/parse_param.c — transformParamRef()
📖 Further reading: PREPARE
Confidence assessment
✅ HIGH confidence
Stable and well-documented. Type inference for parameters is consistent across versions. Edge case: anonymous prepared statements sent via the extended query protocol may produce this error at the protocol level rather than as a SQL error, with a different presentation in some client libraries.
See also
🔗 Related errors
📄 Reference pages