Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Adding an enum label and using it as a default produces a plan that fails with SQLSTATE 55P04 #600

Description

@christophostertag

Summary

Adding an enum label and changing a column default to that label produces a successful plan, but applying the saved plan fails because both statements execute in the same transaction. PostgreSQL requires the new label to be committed before it can be used.

Observed with pgschema 1.13.0 and PostgreSQL 18.4, in an isolated synthetic test on 2026-09-13. This report reuses the recorded run; it does not claim a runtime reproduction against current main.

Reproduction

old.sql:

CREATE TYPE public.status AS ENUM ('new', 'done');
CREATE TABLE public.work (
    id integer PRIMARY KEY,
    state public.status NOT NULL DEFAULT 'new'
);
INSERT INTO public.work VALUES (1, 'new');

desired.sql:

CREATE TYPE public.status AS ENUM ('new', 'active', 'done');
CREATE TABLE public.work (
    id integer PRIMARY KEY,
    state public.status NOT NULL DEFAULT 'active'
);

Use two fresh, disposable databases on a local PostgreSQL 18.4 instance. The role must own the target objects and be able to create/drop planning schemas in the planning database. Set PGPASSWORD separately if authentication requires it.

export PGHOST=127.0.0.1 PGPORT=5432 PGUSER=postgres
createdb pgschema_repro
createdb pgschema_repro_plan
psql -X -v ON_ERROR_STOP=1 -d pgschema_repro -f old.sql
pgschema plan --host "$PGHOST" --port "$PGPORT" \
  --db pgschema_repro --user "$PGUSER" --sslmode disable \
  --plan-host "$PGHOST" --plan-db pgschema_repro_plan \
  --plan-user "$PGUSER" --plan-sslmode disable \
  --file desired.sql --output-json plan.json --output-sql plan.sql --no-color
pgschema apply --host "$PGHOST" --port "$PGPORT" \
  --db pgschema_repro --user "$PGUSER" --sslmode disable \
  --plan plan.json --auto-approve --no-color

Observed result

Planning exits successfully. The generated SQL is:

ALTER TYPE status ADD VALUE 'active' AFTER 'new';

ALTER TABLE work ALTER COLUMN state SET DEFAULT 'active'::status;

Both steps are in the same groups[0].steps array in plan.json. Applying exits 1:

Error: failed to execute concatenated statements in group 1: ERROR: unsafe use of new value "active" of enum type status (SQLSTATE 55P04)

The recorded before/after catalog and row snapshots were unchanged after the failed apply. This is a migration-completion failure, with rollback observed in this case.

Expected behavior

The plan should express the required commit boundary between adding the enum value and using it. If that cannot be represented safely, planning should clearly reject the transition and explain the required staged migration, rather than emit an apparently executable plan that necessarily fails.

A successful migration should retain row (1, 'new'), preserve enum order new, active, done, and make this insert use the new default:

INSERT INTO public.work (id) VALUES (2);
SELECT state = 'active' FROM public.work WHERE id = 2; -- true

Splitting this migration changes its atomicity; the plan should make that explicit and account for recovery if the later step fails.

Related code / issue search

No matching issue was found in the open/closed issue search on 2026-09-13. Existing enum reports about type-name truncation and text-to-enum casts concern different transitions.

At inspected main commit 319b88c83d62b2c9a62eff7a09ec6563954bcf4b, internal/diff/type.go still marks enum alteration statements as CanRunInTransaction: true. This is supporting code inspection, not a new runtime test.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions