{"record":{"id":"ae215f25e9478a28","repo":"dotnet/efcore","slug":"the-current-migration-sql-generator-sqlgenerator","errorCode":null,"errorMessage":"The current migration SQL generator '{sqlGeneratorType}' is unable to generate SQL for operations of type '{operationType}'.","messagePattern":"The current migration SQL generator '(.+?)' is unable to generate SQL for operations of type '(.+?)'\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs","lineNumber":156,"sourceCode":"    /// </summary>\n    /// <remarks>\n    ///     This method uses a double-dispatch mechanism to call one of the 'Generate' methods that are\n    ///     specific to a certain subtype of <see cref=\"MigrationOperation\" />. Typically database providers\n    ///     will override these specific methods rather than this method. However, providers can override\n    ///     this methods to handle provider-specific operations.\n    /// </remarks>\n    /// <param name=\"operation\">The operation.</param>\n    /// <param name=\"model\">The target model which may be <see langword=\"null\" /> if the operations exist without a model.</param>\n    /// <param name=\"builder\">The command builder to use to build the commands.</param>\n    protected virtual void Generate(\n        MigrationOperation operation,\n        IModel? model,\n        MigrationCommandListBuilder builder)\n    {\n        var operationType = operation.GetType();\n        if (!GenerateActions.TryGetValue(operationType, out var generateAction))\n        {\n            throw new InvalidOperationException(RelationalStrings.UnknownOperation(GetType().ShortDisplayName(), operationType));\n        }\n\n        generateAction(this, operation, model, builder);\n    }\n\n    /// <summary>\n    ///     Builds commands for the given <see cref=\"AddColumnOperation\" /> by making calls on the given\n    ///     <see cref=\"MigrationCommandListBuilder\" />.\n    /// </summary>\n    /// <param name=\"operation\">The operation.</param>\n    /// <param name=\"model\">The target model which may be <see langword=\"null\" /> if the operations exist without a model.</param>\n    /// <param name=\"builder\">The command builder to use to build the commands.</param>\n    /// <param name=\"terminate\">Indicates whether or not to terminate the command after generating SQL for the operation.</param>\n    protected virtual void Generate(\n        AddColumnOperation operation,\n        IModel? model,\n        MigrationCommandListBuilder builder,\n        bool terminate = true)","sourceCodeStart":138,"sourceCodeEnd":174,"githubUrl":"https://github.com/dotnet/efcore/blob/dbf9771522148d61a2467854921bd5dc6f6e6916/src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs#L138-L174","documentation":"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.","triggerScenarios":"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)`.","commonSituations":"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.","solutions":["Register/handle the operation: override the appropriate `Generate` method in the provider's MigrationsSqlGenerator for the custom operation type.","Use operations that the current provider's SQL generator supports.","If you wrote a custom operation, also write the matching `Generate(MyCustomOp)` override.","Verify the provider package version matches the operation types you use."],"exampleFix":"// before\nmigrationBuilder.Operations.Add(new MyCustomOperation());\n// generator throws: unknown operation\n// after (provider author)\nprotected override void Generate(MyCustomOperation op, IModel? model, MigrationCommandListBuilder builder)\n{ /* emit SQL */ }","handlingStrategy":"validation","validationCode":"// Before adding a custom operation to a migration, confirm a generator exists for its type.\nvar generator = db.GetService<IMigrationsSqlGenerator>();\nvar supported = generator.GetType().GetMethods()\n    .Any(m => m.Name == \"Generate\" && m.GetParameters().Length > 1 && m.GetParameters()[0].ParameterType == typeof(MyCustomOperation));\nif (!supported) throw new NotSupportedException(\"No SQL generator for MyCustomOperation; register one in the provider.\");","typeGuard":"bool OperationIsSupported(IMigrationsSqlGenerator gen, MigrationOperation op)\n    => MigrationsSqlGeneratorHasGeneratorFor(gen, op.GetType());","tryCatchPattern":"try { migrator.GenerateMigrationCommands(migration); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"unable to generate SQL\"))\n{\n    // Operation type unsupported by this provider: report op type + provider, fall back to raw SQL or a different provider.\n    logger.LogError(ex, \"Unsupported migration operation for current SQL generator.\");\n    throw;\n}","preventionTips":["If you author a custom `MigrationOperation`, also implement a matching `Generate(op)` override in the provider's `MigrationsSqlGenerator`.","Do not pass provider-specific operations to a different provider's generator.","Keep the EF provider package version in sync with the operation types you use."],"tags":["efcore","migrations","sql-generation","custom-operation","provider","relational"],"analyzedSha":"dbf9771522148d61a2467854921bd5dc6f6e6916","analyzedAt":"2026-08-06T20:46:03.226Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}