dotnet/efcore · error · InvalidOperationException

Current value parameter '{parameter}' is not allowed on dele

Error message

Current value parameter '{parameter}' is not allowed on delete stored procedure '{sproc}'. Use HasOriginalValueParameter() instead.

What it means

Thrown when a current-value parameter (HasParameter) is configured on a Delete stored procedure. Deletes only consume original values (e.g. keys and concurrency tokens), not current values. The validator rejects non-original-value parameters on delete sprocs and suggests HasOriginalValueParameter.

Source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:732

                    if (storeObjectIdentifier.StoreObjectType == StoreObjectType.InsertStoredProcedure)
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.StoredProcedureOriginalValueParameterOnInsert(
                                parameter.Name, storeObjectIdentifier.DisplayName()));
                    }
                }
                else
                {
                    if (!properties.TryGetAndRemove(parameter.PropertyName, out property))
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.StoredProcedureParameterNotFound(
                                parameter.PropertyName, entityType.DisplayName(), storeObjectIdentifier.DisplayName()));
                    }

                    if (storeObjectIdentifier.StoreObjectType == StoreObjectType.DeleteStoredProcedure)
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.StoredProcedureCurrentValueParameterOnDelete(
                                parameter.Name, storeObjectIdentifier.DisplayName()));
                    }

                    if (parameter.Direction.HasFlag(ParameterDirection.Input))
                    {
                        switch (storeObjectIdentifier.StoreObjectType)
                        {
                            case StoreObjectType.InsertStoredProcedure:
                                if (property.GetBeforeSaveBehavior() != PropertySaveBehavior.Save)
                                {
                                    throw new InvalidOperationException(
                                        RelationalStrings.StoredProcedureInputParameterForInsertNonSaveProperty(
                                            parameter.Name,
                                            storeObjectIdentifier.DisplayName(),
                                            parameter.PropertyName,
                                            entityType.DisplayName(),
                                            property.GetBeforeSaveBehavior()));

View on GitHub (pinned to dbf9771522)

Solutions

  1. Replace HasParameter with HasOriginalValueParameter on the delete sproc.
  2. Remove the parameter if it is not needed for the delete operation.

Example fix

// before
.DeleteStoredProcedure("sp_DeleteBlog", sp =>
{
    sp.HasParameter("RowVersion");
});

// after
.DeleteStoredProcedure("sp_DeleteBlog", sp =>
{
    sp.HasOriginalValueParameter("RowVersion");
});
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in modelBuilder.Model.GetEntityTypes())
{
    var del = et.GetDeleteStoredProcedure();
    if (del != null && del.Parameters.Any(p => p.ForOriginalValue != true && p.PropertyName != null))
        throw new InvalidOperationException($"{et.DisplayName()} delete sproc has current-value params");
}

Try / catch

try { _ = ctx.Model; } catch (InvalidOperationException ex) when (ex.Message.Contains("not allowed on delete stored procedure")) { /* replace HasParameter with HasOriginalValueParameter */ }

Prevention

When it happens

Trigger: .DeleteStoredProcedure().HasParameter("RowVersion"); using current-value parameter config on a delete sproc, typically for a concurrency token.

Common situations: Copy-pasting insert/update parameter config onto a delete sproc; assuming a concurrency token should be a current-value param.

Related errors


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