dotnet/efcore · error · InvalidOperationException

Original value parameter '{parameter}' is not allowed on ins

Error message

Original value parameter '{parameter}' is not allowed on insert stored procedure '{sproc}'. Use HasParameter() instead.

What it means

Thrown when an original-value parameter (HasOriginalValueParameter) is configured on an Insert stored procedure. Inserts only use current values; original values have no meaning before a row exists. The validator rejects ForOriginalValue==true parameters on insert sprocs and suggests HasParameter instead.

Source

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

        var originalValueProperties = new Dictionary<string, IProperty>(properties);
        var parameterNames = new HashSet<string>();
        foreach (var parameter in sproc.Parameters)
        {
            IProperty? property = null;
            if (parameter.PropertyName != null)
            {
                if (parameter.ForOriginalValue == true)
                {
                    if (!originalValueProperties.TryGetAndRemove(parameter.PropertyName, out property))
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.StoredProcedureParameterNotFound(
                                parameter.PropertyName, entityType.DisplayName(), storeObjectIdentifier.DisplayName()));
                    }

                    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()));

View on GitHub (pinned to dbf9771522)

Solutions

  1. Replace HasOriginalValueParameter with HasParameter on the insert sproc.
  2. Remove the original-value parameter entirely if it is not needed for insert.

Example fix

// before
.InsertStoredProcedure("sp_InsertBlog", sp =>
{
    sp.HasOriginalValueParameter("CreatedAt");
});

// after
.InsertStoredProcedure("sp_InsertBlog", sp =>
{
    sp.HasParameter("CreatedAt");
});
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in modelBuilder.Model.GetEntityTypes())
{
    var ins = et.GetInsertStoredProcedure();
    if (ins != null && ins.Parameters.Any(p => p.ForOriginalValue == true))
        throw new InvalidOperationException($"{et.DisplayName()} insert sproc has original-value params");
}

Try / catch

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

Prevention

When it happens

Trigger: .InsertStoredProcedure().HasOriginalValueParameter("RowVersion"); mixing concurrency-token-style original-value params onto an insert sproc.

Common situations: Copy-pasting update/delete sproc config (which may use original values) onto an insert sproc.

Related errors


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