# 55P04 — unsafe_new_enum_value_usage

> Source-backed reference for PostgreSQL SQLSTATE 55P04.
---

# 55P04

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

`55P04` protects the commit-before-use rule for a newly added enum value. It is raised after PostgreSQL has found an enum tuple that is still uncommitted and marked as unsafe, not because the label has invalid syntax.

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

| Field | Value |
| --- | --- |
| SQLSTATE | `55P04` |
| Condition | `unsafe_new_enum_value_usage` |
| Status | `active` |
| Known present by | `12.0` |
| Locked snapshots | `12.22, 13.23, 14.24, 15.19, 16.15, 17.11, 18.6, 19beta3` |
| Macros | `ERRCODE_UNSAFE_NEW_ENUM_VALUE_USAGE` |
| Aliases | `—` |

<!-- source facts: data/errcodes/55P04.json -->
<!-- END SQLSTATE FACTS -->

## Meaning {#meaning}

The fixed `enum.c` guard first accepts a tuple already hinted committed, then checks the tuple's transaction ID. It also accepts a value not listed by `EnumUncommitted()`, because such a value cannot outlive its owning type. Only the remaining uncommitted value is rejected with the exact primary, detail, and hint below. Thus an `ALTER TYPE ... ADD VALUE` and a use of that new label in one uncommitted transaction can reach `55P04`, while an already committed label does not.

## Messages {#messages}

- Primary template: `unsafe use of new value "%s" of enum type %s`
- Detail: none in this call group.
- Hint: `New enum values must be committed before they can be used.`

The `%s` values are the enum label and formatted enum type name from the tuple; they are diagnostic data, not a value-format recipe.

## Diagnosis {#diagnosis}

Preserve the enum label, type name, SQLSTATE, severity, and transaction status. Check whether the value was added earlier in the same still-open transaction and whether the failed use is an enum input/cast or another expression that resolves the enum value. Distinguish this guard from an invalid enum label (`22P02`); `22P04` is a COPY file-format condition, not this enum guard. Also distinguish a duplicate `ADD VALUE` operation.

## Response {#response}

First recover the transaction after the `ERROR`: issue `ROLLBACK`, or use an appropriate `ROLLBACK TO SAVEPOINT` when the savepoint was placed so the earlier `ADD VALUE` remains. Do not use the label while the addition is still uncommitted. If a full rollback or savepoint rollback discarded the `ADD VALUE`, issue it again in a new transaction and `COMMIT`; if a savepoint preserved it, commit that transaction before using the label. Then start or continue a transaction that can see the committed catalog row. In autocommit, fix the commit boundary and retry the input; do not retry the same uncommitted sequence.

## Versions {#versions}

The locked catalogue records this condition from 12.0; fixed source coverage is PostgreSQL 18.6. The catalogue boundary does not assert that the guard had no earlier private or unresolved form.

## Related {#related}

[`22P02`](../22p02/), [`25006`](../25006/), [`23505`](../23505/)

## Sources {#sources}

[src/backend/utils/adt/enum.c#L68-102](https://github.com/postgres/postgres/blob/724edf9bde9d356724ad384a2e196edc3c9f80f7/src/backend/utils/adt/enum.c#L68)

The structured [evidence record](../data/evidence/55p04.json) records the exact guard and message group; no natural runtime case is claimed.
