# 42P08 — Ambiguous parameter type

> PostgreSQL SQLSTATE 42P08: Ambiguous parameter type (ambiguous_parameter), source-backed diagnosis and recovery guidance.
---

# 42P08 — Ambiguous parameter type

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

`42P08` (**ambiguous_parameter**) means a parameter marker exists, but parse analysis cannot make its type consistent or specific enough. The exact SQLSTATE and parser branch matter because similar primary text can be emitted by a different condition.

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

| Field | Value |
| --- | --- |
| SQLSTATE | `42P08` |
| Condition | `ambiguous_parameter` |
| 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_AMBIGUOUS_PARAMETER` |
| Aliases | `—` |

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

## Meaning {#meaning}

The variable-parameter coercion hook first records a target type for an unknown parameter. If a later context requests a different type, it raises ERROR `inconsistent types deduced for parameter $%d` with DETAIL `%s versus %s`. A later parameter-resolution walk raises ERROR `could not determine data type of parameter $%d` when the resolved parameter type does not match the externally supplied type array. These are two selected `42P08` guards, not one generic “bind failed” message.

The primary `could not determine data type of parameter $%d` also appears in the var-parameter completion check in `postgres.c` with `ERRCODE_INDETERMINATE_DATATYPE` (`42P18`). Read the SQLSTATE and source path together: `42P08` is the selected mismatch during parameter resolution, while `42P18` is an unresolved type after analysis; an out-of-range marker is `42P02`.

## Diagnosis {#diagnosis}

Record the parameter number, every expression context, and DETAIL. For the inconsistent-types branch, compare the two type names in DETAIL and find the contexts that imposed them. For the unresolved-type branch, inspect the PREPARE/extended-query parameter type array and the final inferred type. Keep missing markers (`42P02`), Bind count violations (`08P01`), and alias/column ambiguity separate from this type-resolution failure.

## Response {#response}

Declare the parameter type in PREPARE or cast it at a deliberate expression boundary. If two contexts genuinely need different types, split the parameters; otherwise make the contexts agree. Do not cast to an arbitrary broad type: verify operators, indexes, null semantics, and serialization. If the `ERROR` occurred inside an explicit transaction, roll back to a suitable savepoint or roll back the transaction before retrying.

## Messages {#messages}

The selected `42P08` variants are explicit `ERROR`s:

| Guard | Primary | DETAIL |
| --- | --- | --- |
| conflicting inferred target types | `inconsistent types deduced for parameter $%d` | `%s versus %s` |
| final parameter type mismatch | `could not determine data type of parameter $%d` | none |

The same second primary can carry `42P18` when emitted by the separate unresolved-type completion guard; the SQLSTATE is part of the message identity.

## Versions {#versions}

From 7.4 through 18.6 and 19beta3; that catalogue range is not a precise introduction claim. The selected two `42P08` guards and the nearby `42P18` boundary are fixed 18.6 source paths; no runtime parameter case was run.

## Related {#related}

- [`42P02`](../42p02/)
- [`42P09`](../42p09/)
- [`42804`](../42804/)

## Sources {#sources}
- `src.errcodes.42P08.18.6` — `src/backend/utils/errcodes.txt` line 388, fixed at `724edf9bde9d356724ad384a2e196edc3c9f80f7`; SHA-256 `6e8de346643ba84aa3c9c6a73360acfc7b2dfb89162c06c08ce9bf5bcd5bbcba` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/errcodes.txt#L388)).

- `src.call.42P08.c2cfa81ed9389a1bddf8ec41` — `src/backend/parser/parse_param.c` lines 220-227, fixed at `724edf9bde9d356724ad384a2e196edc3c9f80f7`; SHA-256 `4aab2ecc770fcda619b26ac12beaf7e527542b56f55eb45879b72e92442e8a28` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/parser/parse_param.c#L220-L227)).
- `src.call.42P08.18ba6576d169dfdf614df72d` — `src/backend/parser/parse_param.c` lines 308-312, fixed at `724edf9bde9d356724ad384a2e196edc3c9f80f7`; SHA-256 `4aab2ecc770fcda619b26ac12beaf7e527542b56f55eb45879b72e92442e8a28` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/parser/parse_param.c#L308-L312)).
- `src.call.42P08.unresolved-boundary` — `src/backend/tcop/postgres.c` lines 725-736, fixed at `724edf9bde9d356724ad384a2e196edc3c9f80f7`; SHA-256 `9fb62275b1badf94d01ab351337b60410cd9b3ab1fe63fa9f23d6d2185a21061` ([source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L725-L736)).
- `src.calls.REL_18_6.42P08` — resolved core call groups; SHA-256 `9ee8a0e81d8f0825c5c1ae45583439859a26e602bdd4ce2f2a62aa278867ccbf`.
- [`authored evidence`](../data/evidence/42p08.json) — source claims, message roles, and runtime boundary.
