dotnet/efcore · error · NotSupportedException

The 'Down' method for this migration has not been…

Error message

The 'Down' method for this migration has not been implemented. Both the 'Up' and 'Down' methods must be implemented to support reverting migrations.

What it means

Migration.Down(MigrationBuilder) has its default implementation throw NotSupportedException. The base class deliberately does this so that 'down' migrations fail loudly unless each migration explicitly overrides Down with the inverse operations. Triggered whenever EF tries to revert past this migration (e.g. 'dotnet ef database update <PreviousMigration>' or Migrator with a target before this one).

Solutions

  1. Override protected override void Down(MigrationBuilder migrationBuilder) in the migration and emit the inverse of each Up operation (DropColumn, DropTable, etc.).
  2. If the migration is the latest and you never revert, you can ignore it — but add Down anyway for safety.
  3. Use 'dotnet ef migrations remove' instead of 'update <previous>' to undo the most recent migration when Down is missing.

Example fix

// before
public partial class AddAudit : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
        => migrationBuilder.AddColumn<string>("User", "Orders");
    // Down omitted -> throws
}

// after
public partial class AddAudit : Migration
{
    protected override void Up(MigrationBuilder migrationBuilder)
        => migrationBuilder.AddColumn<string>("User", "Orders");

    protected override void Down(MigrationBuilder migrationBuilder)
        => migrationBuilder.DropColumn("User", "Orders");
}
Defensive patterns

Strategy: validation

Validate before calling

// Scan migrations for a missing Down override before applying
foreach (var m in db.GetService<IMigrationsAssembly>().Migrations.Values)
{
    var down = m.GetType().GetMethod(
        "Down",
        BindingFlags.Instance | BindingFlags.NonPublic,
        null, new[] { typeof(MigrationBuilder) }, null);
    if (down?.DeclaringType == typeof(Migration))
        throw new InvalidOperationException(
            $"Migration {m.GetType().Name} has no Down override.");
}

Prevention

When it happens

Trigger: Calling Database.Migrate(previousMigration), 'dotnet ef migrations remove' on a migration without Down, 'dotnet ef database update' to an earlier migration, or programmatic revert where the migration class never overrode Down.

Common situations: Scaffolder/emitted migration where only Up was written; hand-written migration left half-finished; third-party migration without a Down; using a migration generated by an older tooling version.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/c4358d523af4c174. Report an issue: GitHub.

Appendix: source

Thrown at src/EFCore.Relational/Migrations/Migration.cs:142

    ///     Builds the operations that will migrate the database 'down'.
    /// </summary>
    /// <remarks>
    ///     <para>
    ///         That is, builds the operations that will take the database from the state left in by
    ///         this migration so that it returns to the state that it was in before this migration was applied.
    ///     </para>
    ///     <para>
    ///         This method must be overridden in each class that inherits from <see cref="Migration" /> if
    ///         both 'up' and 'down' migrations are to be supported. If it is not overridden, then calling it
    ///         will throw and it will not be possible to migrate in the 'down' direction.
    ///     </para>
    ///     <para>
    ///         See <see href="https://aka.ms/efcore-docs-migrations">Database migrations</see> for more information and examples.
    ///     </para>
    /// </remarks>
    /// <param name="migrationBuilder">The <see cref="MigrationBuilder" /> that will build the operations.</param>
    protected virtual void Down(MigrationBuilder migrationBuilder)
        => throw new NotSupportedException(RelationalStrings.MigrationDownMissing);

    private List<MigrationOperation> BuildOperations(Action<MigrationBuilder> buildAction)
    {
        var migrationBuilder = new MigrationBuilder(ActiveProvider);
        buildAction(migrationBuilder);

        return migrationBuilder.Operations;
    }
}

View on GitHub (pinned to 3a2006ef56)