dotnet/efcore · error · InvalidOperationException
The number of key column types
Error message
The number of key column types ({typesCount}) doesn't match the number of key columns ({columnsCount}) for the data modification operation on '{table}'. Provide the same number of key column types and key columns. What it means
Thrown when an UpdateData operation supplies KeyColumnTypes whose length differs from KeyColumns. EF needs a one-to-one mapping so it can resolve a type mapping per key parameter.
Solutions
- Make keyColumnTypes length equal to keyColumns length, one store type per key column.
- Drop keyColumnTypes entirely to fall back on the model.
- Re-scaffold the migration so types are written consistently.
Example fix
// before
migrationBuilder.UpdateData(
table: "Users",
keyColumns: new[] { "TenantId", "Id" },
keyColumnTypes: new[] { "int" }, // length 1 != 2
keyValues: new object[,] { { 1, 10 } },
columns: new[] { "Name" },
values: new object[,] { { "Ann" } });
// after
migrationBuilder.UpdateData(
table: "Users",
keyColumns: new[] { "TenantId", "Id" },
keyColumnTypes: new[] { "int", "int" },
keyValues: new object[,] { { 1, 10 } },
columns: new[] { "Name" },
values: new object[,] { { "Ann" } }); Defensive patterns
Strategy: validation
Validate before calling
static void CheckKeyTypeCount(string[] keyColumns, string[]? keyColumnTypes, string table)
{
if (keyColumnTypes is not null && keyColumnTypes.Length != keyColumns.Length)
throw new ArgumentException($"{table}: keyColumnTypes length must equal keyColumns length");
} Prevention
- Derive keyColumnTypes from keyColumns whenever explicit types are needed.
- Prefer model-driven type resolution and omit keyColumnTypes.
- Re-scaffold to keep arrays in sync.
When it happens
Trigger: migrationBuilder.UpdateData(...) with keyColumnTypes: of wrong length. Checked after the row-count check in GenerateModificationCommands(UpdateDataOperation).
Common situations: Hand-edited composite-key update where a key column was added but keyColumnTypes was not updated. SQLite migrations that explicitly declare key types.
Related errors
- The number of column types
- The number of key values
- The number of value rows
- The number of values
- values were provided in CreateIndexOperations.IsDescending…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/c394428143b2bd3b.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs:1082
if (operation.Columns.Length != operation.Values.GetLength(1))
{
throw new InvalidOperationException(
RelationalStrings.UpdateDataOperationValuesCountMismatch(
operation.Values.GetLength(1), operation.Columns.Length, FormatTable(operation.Table, operation.Schema)));
}
if (operation.KeyValues.GetLength(0) != operation.Values.GetLength(0))
{
throw new InvalidOperationException(
RelationalStrings.UpdateDataOperationRowCountMismatch(
operation.Values.GetLength(0), operation.KeyValues.GetLength(0), FormatTable(operation.Table, operation.Schema)));
}
if (operation.KeyColumnTypes != null
&& operation.KeyColumns.Length != operation.KeyColumnTypes.Length)
{
throw new InvalidOperationException(
RelationalStrings.UpdateDataOperationKeyTypesCountMismatch(
operation.KeyColumnTypes.Length, operation.KeyColumns.Length, FormatTable(operation.Table, operation.Schema)));
}
if (operation.ColumnTypes != null
&& operation.Columns.Length != operation.ColumnTypes.Length)
{
throw new InvalidOperationException(
RelationalStrings.UpdateDataOperationTypesCountMismatch(
operation.ColumnTypes.Length, operation.Columns.Length, FormatTable(operation.Table, operation.Schema)));
}
if (operation.KeyColumnTypes == null
&& model == null)
{
throw new InvalidOperationException(
RelationalStrings.UpdateDataOperationNoModel(
FormatTable(operation.Table, operation.Schema)));View on GitHub (pinned to 3a2006ef56)