# 42P18 — Indeterminate datatype

> Source-backed reference for PostgreSQL SQLSTATE 42P18.
---

# 42P18 — Indeterminate datatype

## At a glance {#at-a-glance}

`42P18` (**indeterminate_datatype**) Type inference fails when an expression or protocol parameter has no determinate type.

<!-- BEGIN SQLSTATE FACTS: generated by scripts/generate.py; do not edit -->

| Field | Value |
| --- | --- |
| SQLSTATE | `42P18` |
| Condition | `indeterminate_datatype` |
| Status | `active` |
| Known present by | `7.4` |
| Locked snapshots | `9.0.23, 9.1.24, 9.2.24, 9.3.25, 9.4.26, 9.5.25, 9.6.24, 10.23, 11.22, 12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_INDETERMINATE_DATATYPE` |
| Aliases | `—` |

<!-- source facts: data/errcodes/42P18.json -->
<!-- END SQLSTATE FACTS -->

## Meaning {#meaning}

The parser cannot assign a determinate type to an expression or protocol parameter. Core 18.6 explicitly reports empty `ARRAY[]`, and `pg_analyze_and_rewrite_varparams` performs a final pass that rejects every parameter still `InvalidOid` or `UNKNOWNOID`, such as `$1` with no constraining context. These are different from 42P08, where inputs imply incompatible types, and 42P02, where the parameter reference itself is missing.

## Diagnosis {#diagnosis}

Use the exact location or parameter number in the response. For `ARRAY[]`, inspect the surrounding expression and cast it to the intended element type; for `$n`, inspect the Parse/extended-query parameter types and every context that should constrain it, then confirm the final parameter-type pass can resolve the OID. A client that sends no type OID may leave this decision to the server. A conflicting deduction is 42P08; a reference to a parameter that was not declared is 42P02.

## Response {#response}

Add an explicit, semantically correct cast or supply parameter type information, then verify operators and result columns still have the intended types. Do not silence the error by casting everything to text; that can change index use and function/operator selection. Retry the parse or statement only after the corrected definition is known. If the ERROR was raised inside an explicit transaction, `ROLLBACK` or `ROLLBACK TO` a pre-error savepoint before sending the corrected statement.

## Messages {#messages}

Representative source messages include: message: `cannot determine type of empty array`; HINT: `Explicitly cast to the desired type, for example ARRAY[]::integer[].`; message: `could not determine data type of parameter $%d`. Placeholders are filled by the actual object, column, or parameter.

## Versions {#versions}

The locked catalogue shows this condition by PostgreSQL 7.4; behavior here is fixed to PostgreSQL 18.6 source. Catalogue presence is a range boundary, not proof that every message or feature began in that release.

## Related {#related}

- [`42P08`](../42p08/)
- [`42P02`](../42p02/)

## Sources {#sources}

Source messages, line anchors, and evidence limits are recorded in [authored evidence](../data/evidence/42p18.json).

- `src/backend/parser/parse_expr.c:2102-2107` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/parser/parse_expr.c#L2102-L2107))
- `src/backend/tcop/postgres.c:733-736` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L733-L736))
