dotnet/efcore · error · InvalidOperationException

The current migration SQL generator '{sqlGeneratorType}' is

Error message

The current migration SQL generator '{sqlGeneratorType}' is unable to generate SQL for operations of type '{operationType}'.

What it means

Thrown by MigrationsSqlGenerator.Generate when it receives a `MigrationOperation` whose runtime type has no registered generator action. The SQL generator uses double-dispatch keyed by operation type; an unknown operation type means no provider `Generate(op)` overload handles it.

Source

Thrown at src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs:156

    /// </summary>
    /// <remarks>
    ///     This method uses a double-dispatch mechanism to call one of the 'Generate' methods that are
    ///     specific to a certain subtype of <see cref="MigrationOperation" />. Typically database providers
    ///     will override these specific methods rather than this method. However, providers can override
    ///     this methods to handle provider-specific operations.
    /// </remarks>
    /// <param name="operation">The operation.</param>
    /// <param name="model">The target model which may be <see langword="null" /> if the operations exist without a model.</param>
    /// <param name="builder">The command builder to use to build the commands.</param>
    protected virtual void Generate(
        MigrationOperation operation,
        IModel? model,
        MigrationCommandListBuilder builder)
    {
        var operationType = operation.GetType();
        if (!GenerateActions.TryGetValue(operationType, out var generateAction))
        {
            throw new InvalidOperationException(RelationalStrings.UnknownOperation(GetType().ShortDisplayName(), operationType));
        }

        generateAction(this, operation, model, builder);
    }

    /// <summary>
    ///     Builds commands for the given <see cref="AddColumnOperation" /> by making calls on the given
    ///     <see cref="MigrationCommandListBuilder" />.
    /// </summary>
    /// <param name="operation">The operation.</param>
    /// <param name="model">The target model which may be <see langword="null" /> if the operations exist without a model.</param>
    /// <param name="builder">The command builder to use to build the commands.</param>
    /// <param name="terminate">Indicates whether or not to terminate the command after generating SQL for the operation.</param>
    protected virtual void Generate(
        AddColumnOperation operation,
        IModel? model,
        MigrationCommandListBuilder builder,
        bool terminate = true)

View on GitHub (pinned to dbf9771522)

Solutions

  1. Register/handle the operation: override the appropriate `Generate` method in the provider's MigrationsSqlGenerator for the custom operation type.
  2. Use operations that the current provider's SQL generator supports.
  3. If you wrote a custom operation, also write the matching `Generate(MyCustomOp)` override.
  4. Verify the provider package version matches the operation types you use.

Example fix

// before
migrationBuilder.Operations.Add(new MyCustomOperation());
// generator throws: unknown operation
// after (provider author)
protected override void Generate(MyCustomOperation op, IModel? model, MigrationCommandListBuilder builder)
{ /* emit SQL */ }
Defensive patterns

Strategy: validation

Validate before calling

// Before adding a custom operation to a migration, confirm a generator exists for its type.
var generator = db.GetService<IMigrationsSqlGenerator>();
var supported = generator.GetType().GetMethods()
    .Any(m => m.Name == "Generate" && m.GetParameters().Length > 1 && m.GetParameters()[0].ParameterType == typeof(MyCustomOperation));
if (!supported) throw new NotSupportedException("No SQL generator for MyCustomOperation; register one in the provider.");

Type guard

bool OperationIsSupported(IMigrationsSqlGenerator gen, MigrationOperation op)
    => MigrationsSqlGeneratorHasGeneratorFor(gen, op.GetType());

Try / catch

try { migrator.GenerateMigrationCommands(migration); }
catch (InvalidOperationException ex) when (ex.Message.Contains("unable to generate SQL"))
{
    // Operation type unsupported by this provider: report op type + provider, fall back to raw SQL or a different provider.
    logger.LogError(ex, "Unsupported migration operation for current SQL generator.");
    throw;
}

Prevention

When it happens

Trigger: Passing a custom/provider-specific `MigrationOperation` subtype to a SQL generator that does not know how to emit SQL for it; using operations from another provider (e.g. a SqlServer-specific operation under SQLite) without a matching generator; manual `migrationBuilder.Operations.Add(customOp)`.

Common situations: Custom migration operations authored without registering a generator; cross-provider migration scripts; provider version mismatch where an operation type exists but the generator overload was removed/renamed.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/ae215f25e9478a28. Report an issue: GitHub.