dotnet/efcore · error · InvalidOperationException

command.EntityState.ToString()

Error message

command.EntityState.ToString()

What it means

Thrown at the `default` arm of a switch over `command.EntityState` in MigrationsModelDiffer seed-operation generation. Only Added/Modified/Deleted are handled; any other EntityState value is an internal invariant violation. The thrown message is just the raw enum string, indicating an unexpected/broken command state rather than a user configuration problem.

Source

Thrown at src/EFCore.Relational/Migrations/Internal/MigrationsModelDiffer.cs:2437

                            .Select(c => (IColumn)c.Column!);
                        var anyKeyColumnDropped = keyColumns.Any(c => diffContext.FindDrop(c) != null);

                        yield return new DeleteDataOperation
                        {
                            Schema = command.Schema,
                            Table = command.TableName,
                            KeyColumns = command.ColumnModifications.Where(col => col.IsKey).Select(col => col.ColumnName).ToArray(),
                            KeyColumnTypes = anyKeyColumnDropped
                                ? keyColumns.Select(col => col.StoreType).ToArray()
                                : null,
                            KeyValues = ToMultidimensionalArray(
                                command.ColumnModifications.Where(col => col.IsKey).Select(col => col.Value).ToArray()),
                            IsDestructiveChange = true
                        };

                        break;
                    default:
                        throw new InvalidOperationException(command.EntityState.ToString());
                }
            }

            if (batchInsertOperation != null)
            {
                yield return batchInsertOperation;
            }
        }
    }

    #endregion

    /// <summary>
    ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
    ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
    ///     any release. You should only use it directly in your code with extreme caution and knowing that
    ///     doing so can result in application failures when updating to a new Entity Framework Core release.
    /// </summary>

View on GitHub (pinned to dbf9771522)

Solutions

  1. If you are feeding custom commands, ensure each command's `EntityState` is Added, Modified, or Deleted before diffing.
  2. If reached through normal EF usage, capture a repro and report an EF Core bug (this is an internal contract violation).
  3. Upgrade or downgrade EF Core to a version without the regression, then re-test.

Example fix

// before
command.EntityState = EntityState.Unchanged; // fed to differ -> throws
// after
command.EntityState = EntityState.Modified;
Defensive patterns

Strategy: try-catch

Validate before calling

// If you construct commands manually, restrict EntityState to seed-relevant values.
if (command.EntityState is not (EntityState.Added or EntityState.Modified or EntityState.Deleted))
    throw new ArgumentOutOfRangeException(nameof(command.EntityState), command.EntityState, "Must be Added, Modified, or Deleted.");

Type guard

bool IsSeedEntityState(EntityState s) => s is EntityState.Added or EntityState.Modified or EntityState.Deleted;

Try / catch

try { /* differ / migrate */ }
catch (InvalidOperationException ex) when (ex.Message is "Added" or "Modified" or "Deleted" or "Unchanged" or "Detached")
{
    // internal invariant violation: log command source + EntityState, file an EF Core bug.
    logger.LogCritical(ex, "Unexpected EntityState in differ pipeline.");
    throw;
}

Prevention

When it happens

Trigger: Internal/profiler/test code constructs a ModificationCommand with an EntityState other than Added, Modified, or Deleted (e.g. Unchanged, Detached) and feeds it into the differ's seed-operation generator. Not reachable through normal `HasData`/`Migrate` flows.

Common situations: Custom modification-command pipelines; third-party tooling or a buggy EF provider feeding Detached/Unchanged commands into the differ; an EF Core internal regression after a version upgrade.

Related errors


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