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
- Replace HasParameter with HasOriginalValueParameter on the delete sproc.
- 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
- On delete sprocs use HasOriginalValueParameter for keys and concurrency tokens, never HasParameter.
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
- The property '{entityType}.{property}' is mapped to a result
- No property named '{property}' found on the entity type '{en
- Original value parameter '{parameter}' is not allowed on ins
- Input parameter '{parameter}' of insert stored procedure '{s
- Input parameter '{parameter}' of update stored procedure '{s
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/4470fb6e25980997.
Report an issue: GitHub.