dotnet/efcore · error · ArgumentException

{numSortOrderProperties} values were provided in CreateIndex

Error message

{numSortOrderProperties} values were provided in CreateIndexOperations.IsDescending, but the operation has {numColumns} columns.

What it means

Thrown by the CreateIndexOperation.Columns setter when assigning a new columns array whose length does not match the already-set IsDescending array length. The two arrays must be element-aligned (one sort-order flag per column), so EF rejects any mismatch as an ArgumentException at assignment time.

Source

Thrown at src/EFCore.Relational/Migrations/Operations/CreateIndexOperation.cs:43

    /// </summary>
    public virtual string? Schema { get; set; }

    /// <summary>
    ///     The table that contains the index.
    /// </summary>
    public virtual string Table { get; set; } = null!;

    /// <summary>
    ///     The ordered list of column names for the column that make up the index.
    /// </summary>
    public virtual string[] Columns
    {
        get => _columns!;
        set
        {
            if (_isDescending is not null && _isDescending.Length > 0 && value.Length != _isDescending.Length)
            {
                throw new ArgumentException(RelationalStrings.CreateIndexOperationWithInvalidSortOrder(_isDescending.Length, value.Length));
            }

            _columns = value;
        }
    }

    /// <summary>
    ///     Indicates whether or not the index should enforce uniqueness.
    /// </summary>
    public virtual bool IsUnique { get; set; }

    /// <summary>
    ///     A set of values indicating whether each corresponding index column has descending sort order.
    /// </summary>
    public virtual bool[]? IsDescending
    {
        get => _isDescending;
        set

View on GitHub (pinned to dbf9771522)

Solutions

  1. Ensure the Columns array and the IsDescending array have identical lengths when setting Columns after IsDescending.
  2. Set IsDescending to null before changing the column count, then assign the correctly-sized IsDescending array afterwards.
  3. Construct both arrays together from the same source (e.g. project from the index's columns) so they cannot drift.

Example fix

// before
var op = new CreateIndexOperation
{
    Name = "IX",
    Table = "T",
    IsDescending = new[] { true, false }
};
op.Columns = new[] { "A" }; // length mismatch -> throws

// after
op.Columns = new[] { "A", "B" }; // matches IsDescending length
Defensive patterns

Strategy: validation

Validate before calling

static CreateIndexOperation BuildIndex(string table, string[] cols, bool[]? desc)
{
    if (desc is { Length: > 0 } && desc.Length != cols.Length)
        throw new ArgumentException($"IsDescending length {desc.Length} != columns {cols.Length}");
    return new CreateIndexOperation { Name = "IX_" + table, Table = table, Columns = cols, IsDescending = desc };
}

Prevention

When it happens

Trigger: Setting operation.Columns after operation.IsDescending with arrays of different lengths; creating a CreateIndexOperation where IsDescending was assigned first and Columns is later set to a differently-sized array.

Common situations: Hand-building a CreateIndexOperation in code/migrations with mismatched array sizes; copying an index operation and editing only one of the two arrays; provider/annotation code that mutates Columns after IsDescending is populated.

Related errors


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