# 42P14 — Invalid prepared statement definition

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

# 42P14 — Invalid prepared statement definition

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

`42P14` (**invalid_prepared_statement_definition**) A PREPARE command can fail while defining the prepared statement itself.

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

| Field | Value |
| --- | --- |
| SQLSTATE | `42P14` |
| Condition | `invalid_prepared_statement_definition` |
| 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_INVALID_PSTATEMENT_DEFINITION` |
| Aliases | `—` |

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

## Meaning {#meaning}

The fixed 18.6 `PrepareQuery` path rejects a null or empty name for the SQL `PREPARE` command before the named prepared statement can be registered; the guard exists because the extended protocol has a separate unnamed statement slot. An empty name in a protocol `Parse` message is therefore not automatically `42P14`, and an empty quoted SQL identifier can fail earlier in lexical or parse validation.

## Diagnosis {#diagnosis}

Capture whether the client sent SQL `PREPARE` or an extended-protocol `Parse`, and preserve the exact statement name. Distinguish SQL PREPARE's empty-name guard from a legal unnamed protocol statement, 26000 (prepared statement does not exist), and later parameter/type errors; an empty quoted identifier may fail before this guard is reached.

## Response {#response}

For SQL `PREPARE`, send a non-empty, consistently quoted statement name. For extended protocol, retain the unnamed statement slot when that is intentional instead of translating it into SQL `PREPARE`. If a framework generates names, inspect that naming layer and verify the same session is used for later EXECUTE and DEALLOCATE. An ERROR inside an explicit transaction still requires `ROLLBACK` or `ROLLBACK TO` a pre-error savepoint before the next command.

## Messages {#messages}

Representative source message: `invalid statement name: must not be empty` (ERROR; it has no placeholders).

## 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}

- [`42P05`](../42p05/)
- [`26000`](../26000/)

## Sources {#sources}

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

- `src/backend/commands/prepare.c:73-75` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/commands/prepare.c#L73-L75))
- `src/backend/tcop/postgres.c:1433-1459` ([fixed source](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/tcop/postgres.c#L1433-L1459))
