How can we help you today? How can we help you today?

Oracle target requires manual `flyway repair` after a failed DML-only migration

--------------------------------------------------------------------
SUMMARY
--------------------------------------------------------------------
On Oracle, any migration that fails after modifying data (a DML
statement that runs, then a PL/SQL row-count check that raises an
error because the actual affected-row-count doesn't match the
expected count) leaves a success=0 row in the Flyway schema history
table. Flyway then refuses ALL further `migrate` attempts against
that schema until `flyway repair` is run manually — even after the
migration file itself has been corrected.

The same migration pattern against PostgreSQL does NOT require
`repair` under an equivalent failure: the failed attempt leaves NO
row in flyway_schema_history at all, because Postgres wraps the
migration + Flyway's own history insert in one fully-transactional,
all-or-nothing unit (Postgres supports DDL transactions). Oracle's
Flyway dialect reports supportsDdlTransactions() = false
categorically, so Oracle never gets this same atomicity — even
though our migrations contain no DDL at all, only DML.

--------------------------------------------------------------------
REPRODUCTION STEPS (Oracle)
--------------------------------------------------------------------
1. flyway.conf:
   flyway.outOfOrder=true
   flyway.baselineOnMigrate=true
   flyway.oracle.sqlplus=false
   flyway.executeInTransaction=true   (default)

2. Migration script (DML only, no DDL):

   DECLARE
       l_cnt         PLS_INTEGER;
       l_expectedCnt PLS_INTEGER;
   BEGIN
       l_expectedCnt := 2; -- intentionally wrong; actual match count is 1

       UPDATE some_table
       SET some_column = 'X', updated_at = SYSTIMESTAMP
       WHERE id = 123;

       l_cnt := SQL%ROWCOUNT;
       IF l_cnt IS NULL OR l_cnt != l_expectedCnt THEN
           RAISE_APPLICATION_ERROR(-20000, 'incorrect record count - expected ' || l_expectedCnt || ' but modified ' || l_cnt);
       END IF;
   END;
   /

3. Run `flyway migrate`. Result: migration fails as expected
   (see error below), and the UPDATE itself is correctly rolled
   back (verified: target row unchanged). BUT a success=0 row is
   written to flyway_schema_history for this version.

4. Correct the file (l_expectedCnt := 1) and run `flyway migrate`
   again, WITHOUT running `flyway repair` first.

   Result: Flyway refuses to even attempt the corrected file:

   ERROR: Schema "ADMIN" contains a failed migration to version 20260101000006 !

5. Only after running `flyway repair` (which deletes the success=0
   row) does the corrected migration get picked up and applied
   successfully.

--------------------------------------------------------------------
ACTUAL ERROR OUTPUT
--------------------------------------------------------------------
First (failing) run:

ERROR: Migration of schema "ADMIN" to version "20260101000006 - MISMATCH-TEST" failed! Please restore backups and roll back database and code!
ERROR: Failed to execute script V20260101000006__MISMATCH-TEST.sql
-----------------------------------------------------------------
SQL State  : 72000
Error Code : 20000
Message    : ORA-20000: incorrect record count - expected 2 but modified 1
ORA-06512: at line 24
Location   : ./oracle/admtest/public/V20260101000006__MISMATCH-TEST.sql
Line       : 6

Retry attempt (corrected file, no repair run):

Current version of schema "ADMIN": 20260101000005
outOfOrder mode is active. Migration of schema "ADMIN" may not be reproducible.
ERROR: Schema "ADMIN" contains a failed migration to version 20260101000006 !

flyway repair output:

Successfully repaired schema history table "ADMIN"."flyway_data_migrations" (execution time 00:01.3s).
Manual cleanup of the remaining effects of the failed migration may still be required.



--------------------------------------------------------------------
QUESTION 
--------------------------------------------------------------------
Is there any OFFICIAL, supported Flyway mechanism (OSS or Teams) to
avoid the "contains a failed migration" block for a genuine DML-only
migration failure on Oracle, equivalent to how PostgreSQL's
transactional DDL support avoids ever writing a success=0 row in
the first place? We are not running any DDL in our Oracle
migrations — only DML wrapped in PL/SQL blocks with an application-
level row-count check that raises an error on mismatch.
Azmat
0

Comments

1 comment

  • Dan Calver
    Official comment

    Hi Azmat,

    On Postgres, when a migration fails partway through, the database can undo everything it did — including telling Flyway "this one failed." So Flyway never even writes a record of the attempt. Next time you run migrate, it just looks like the failed attempt never happened.

    Oracle can't offer that guarantee across the board — some things Oracle does (schema changes, in particular) can't be undone once started, no matter what. Because Flyway has to treat Oracle consistently, it plays it safe for every Oracle migration: it always writes down "this one failed" before it can know whether the failure was something undoable (like your data update) or something it couldn't have undone anyway. It can't tell the difference in advance, so it treats a DML-only failure the same as a DDL failure.

    That's why you end up with a leftover "failed" record even though your actual data change rolled back cleanly — Oracle rolled back the data, but Flyway still keeps the paper trail of the failed attempt, and it won't proceed until you clear that paper trail.

    Performing ‘flyway repair’ is the officially supported mechanism to address this issue, to make life easier you could add this as a automatic step in your deployment pipeline that runs before migrate.

     

    Dan Calver

Add comment

Please sign in to leave a comment.