Elixir version
any
Database and Version
any
Ecto Versions
3.14.0
Database Adapter and Versions (postgrex, myxql, etc)
any (Reproduced with `EctoSQL.TestAdapter)
Current behavior
If a migration module does not implement neither the requested callback nor change/0, Ecto.Migrator.up/4 and down/4 raise Ecto.MigrationError but still modify the schema_migrations table. A broken migration applied during tests/development corrupts the state and requires manual intervention.
Repro:
run a broken migration
defmodule InvalidMigration do
use Ecto.Migration
end
assert_raise Ecto.MigrationError, fn ->
Ecto.Migrator.up(TestRepo, 13, InvalidMigration, log: false)
end
# Incorrect: version 13 was recorded even though no migration ran.
assert Ecto.Migrator.migrated_versions(TestRepo) == [1, 2, 3, 13]
Reason:
do_up/5 and do_down/5 return {:error, %Ecto.MigrationError{}}. In async_migrate_maybe_in_transaction/7, fun_with_status unconditionally calls SchemaMigration.up/4 or SchemaMigration.down/4.
Secondary issue:
With strict_version_order: true, up/4 currently checks version ordering only after do_up/5 returns. An out-of-order migration is applied and its version is committed before Ecto.MigrationError is raised:
assert_raise Ecto.MigrationError, fn ->
Ecto.Migrator.up(TestRepo, 0, ValidMigration,
log: false,
strict_version_order: true
)
end
# Incorrect: migration 0 has already run and is recorded.
assert 0 in Ecto.Migrator.migrated_versions(TestRepo)
This contradicts the documented behavior that strict ordering should abort the migration.
Expected behavior
Broken migrations should not affect schema_migrations table. Retrying after fixing the module should execute the migration instead of returning :already_up or :already_down. With strict_version_order: true, version ordering should be validated before executing any migration commands
Elixir version
any
Database and Version
any
Ecto Versions
3.14.0
Database Adapter and Versions (postgrex, myxql, etc)
any (Reproduced with `EctoSQL.TestAdapter)
Current behavior
If a migration module does not implement neither the requested callback nor change/0, Ecto.Migrator.up/4 and down/4 raise Ecto.MigrationError but still modify the schema_migrations table. A broken migration applied during tests/development corrupts the state and requires manual intervention.
Repro:
run a broken migration
Reason:
do_up/5 and do_down/5 return {:error, %Ecto.MigrationError{}}. In async_migrate_maybe_in_transaction/7, fun_with_status unconditionally calls SchemaMigration.up/4 or SchemaMigration.down/4.
Secondary issue:
With strict_version_order: true, up/4 currently checks version ordering only after do_up/5 returns. An out-of-order migration is applied and its version is committed before Ecto.MigrationError is raised:
This contradicts the documented behavior that strict ordering should abort the migration.
Expected behavior
Broken migrations should not affect schema_migrations table. Retrying after fixing the module should execute the migration instead of returning :already_up or :already_down. With strict_version_order: true, version ordering should be validated before executing any migration commands