dotnet/efcore · error · InvalidOperationException
The number of key values
Error message
The number of key values ({valuesCount}) doesn't match the number of key columns ({columnsCount}) for the data modification operation on '{table}'. Provide the same number of key values and key columns. What it means
Thrown when an UpdateData operation's KeyValues 2D array second dimension does not match the number of KeyColumns. Each row of KeyValues must contain exactly one value per key column so EF can build a correct WHERE clause.
Solutions
- Resize the keyValues 2D array so its second dimension equals keyColumns.Length.
- Add the missing key column to both keyColumns and each row of keyValues.
- Re-scaffold the migration with dotnet ef migrations add to regenerate consistent arrays.
Example fix
// before
migrationBuilder.UpdateData(
table: "Users",
keyColumns: new[] { "TenantId", "Id" },
keyValues: new object[,] { { 1 } }, // 1 value, 2 key columns
columns: new[] { "Name" },
values: new object[,] { { "x" } });
// after
migrationBuilder.UpdateData(
table: "Users",
keyColumns: new[] { "TenantId", "Id" },
keyValues: new object[,] { { 1, 10 } },
columns: new[] { "Name" },
values: new object[,] { { "x" } }); Defensive patterns
Strategy: validation
Validate before calling
static void CheckKeyShape(string[] keyColumns, object[,] keyValues, string table)
{
if (keyValues.GetLength(1) != keyColumns.Length)
throw new ArgumentException($"{table}: keyValues second dimension must equal keyColumns.Length");
} Prevention
- Build keyValues with explicit dimensions matching keyColumns.
- When editing migrations, recompute both dimensions together.
- Re-scaffold migrations rather than hand-editing composite keys.
When it happens
Trigger: migrationBuilder.UpdateData(...) where keyValues.GetLength(1) (values per row) != keyColumns.Length. Triggered in GenerateModificationCommands(UpdateDataOperation) at the first shape check.
Common situations: Composite key where one column was forgotten in keyValues. Passing a jagged-looking 2D array mis-sized. Editing a generated migration and dropping a key column without resizing values.
Related errors
- The number of column types
- The number of key column types
- 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/4ab0a146d41a03bd.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Relational/Migrations/MigrationsSqlGenerator.cs:1060
}
builder.Append(sqlBuilder.ToString());
EndStatement(builder);
}
/// <summary>
/// Generates the commands that correspond to the given operation.
/// </summary>
/// <param name="operation">The data operation to generate commands for.</param>
/// <param name="model">The model.</param>
/// <returns>The commands that correspond to the given operation.</returns>
protected virtual IEnumerable<IReadOnlyModificationCommand> GenerateModificationCommands(
UpdateDataOperation operation,
IModel? model)
{
if (operation.KeyColumns.Length != operation.KeyValues.GetLength(1))
{
throw new InvalidOperationException(
RelationalStrings.UpdateDataOperationKeyValuesCountMismatch(
operation.KeyValues.GetLength(1), operation.KeyColumns.Length, FormatTable(operation.Table, operation.Schema)));
}
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)));
}
View on GitHub (pinned to 3a2006ef56)