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.
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:desired.sql: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
PGPASSWORDseparately if authentication requires it.Observed result
Planning exits successfully. The generated SQL is:
Both steps are in the same
groups[0].stepsarray inplan.json. Applying exits 1: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 ordernew, active, done, and make this insert use the new default: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
maincommit319b88c83d62b2c9a62eff7a09ec6563954bcf4b,internal/diff/type.gostill marks enum alteration statements asCanRunInTransaction: true. This is supporting code inspection, not a new runtime test.