How does modifyChangeSets work with preconditions?

Last updated: June 9, 2026

In Liquibase 5.2 and later, you can use preconditions with modifyChangeSets to conditionally include or skip entire groups of changesets in XML, YAML, and JSON changelogs. This page explains how preconditions work in the context of modifyChangeSets and provides syntax examples.

Important notes

  • In Liquibase 5.2+, CONTINUE and MARK_RAN are now supported inside modifyChangeSets preconditions. These values were previously only supported at the changeset level.

  • For the full list of onFail and onError values and their behavior, see What are preconditions?.

How it works

When you add a preConditions block inside modifyChangeSets, Liquibase evaluates the precondition before processing any changesets in the include or includeAll entries nested under that modifyChangeSets block. Changesets inside modifyChangeSets are subject to the precondition. Changesets outside it, such as a top-level include entry, are not affected.

If a changeset already has its own preConditions block, the modifyChangeSets precondition is not applied to that changeset. The changeset-level precondition takes priority.

loading

loading

loading

Precondition attributes

The preConditions element within modifyChangeSets supports the same attributes as changeset-level preconditions.

onFail values

Value

Description

CONTINUE

Skips the changeset. Execution is attempted again on the next update. Continues with the changelog.

HALT

Halts execution of the entire changelog. This is the default.

MARK_RAN

Skips the changeset but marks it as executed in DATABASECHANGELOG. The changeset is not attempted again on subsequent updates.

WARN

Logs a warning and executes the changeset anyway.

onError values

Value

Description

CONTINUE

Skips the changeset on precondition error.

HALT

Halts execution on precondition error. This is the default.

MARK_RAN

Marks the changeset as executed on error without running it.

WARN

Logs a warning and continues on precondition error.

Changeset-level precondition override

If a changeset in an included file already has its own preConditions element, the modifyChangeSets precondition is not applied to that changeset—the changeset-level precondition takes priority. This lets you set a default precondition for a group of changesets while allowing individual changesets to override it.

In the example below, mixed-changes is included inside a modifyChangeSets block that applies an Oracle precondition. The pg-only changeset has its own PostgreSQL precondition and ignores the modifyChangeSets one. The oracle-only changeset has no precondition and inherits the Oracle precondition from modifyChangeSets.

loading

loading

loading

Combining with other modifyChangeSets attributes

Preconditions can be used alongside existing modifyChangeSets attributes like runWith, endDelimiter, and stripComments. In the example below, PostgreSQL SQL files are run with psql and only on PostgreSQL databases.

loading

loading

loading

Backward compatibility

Existing modifyChangeSets blocks without preConditions continue to work exactly as before. Adding preConditions is optional and does not affect the behavior of modifyChangeSets blocks that do not use it.

Known limitations

  • When a changeset is skipped via a modifyChangeSets precondition with onFail=CONTINUE, the UPDATE SUMMARY does not reflect the skipped changeset. The changeset is correctly not executed, but the Filtered out count in the summary remains 0.

  • The update-sql command generates SQL for all changesets regardless of preconditions, because preconditions are evaluated at runtime against a live database.

Related links