dotnet/efcore · error · InvalidOperationException

No property named ' ' found on the entity type ' '…

Error message

No property named '{property}' found on the entity type '{entityType}' corresponding to the parameter on the stored procedure '{sproc}'.

What it means

Thrown in the parameter loop of ValidateSproc for an original-value parameter (parameter.ForOriginalValue == true) whose PropertyName is not present in the originalValueProperties dictionary (RelationalModelValidator.cs:705-712). The dictionary is a copy of the entity's properties; when TryGetAndRemove fails the binding references a property the entity does not have.

Solutions

  1. Point the original-value parameter at an existing property: sp.HasOriginalValueParameter(x => x.CurrentProperty).
  2. If the property was renamed, update the binding to the new name (and consider .HasColumnName to keep the store column name stable).
  3. If the property no longer exists, remove the HasOriginalValueParameter call.
  4. Verify the mapping strategy includes the property (TPT requires base-type PK properties to be added explicitly — see lines 601-631).

Example fix

// before
sp.HasOriginalValueParameter("RowVersion"); // property renamed to VersionTag

// after
sp.HasOriginalValueParameter(x => x.VersionTag).HasName("RowVersion");
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in modelBuilder.Model.GetEntityTypes())
{
    var propNames = et.GetProperties().Select(p => p.Name).ToHashSet();
    foreach (var sproc in new[] { et.GetInsertStoredProcedure(), et.GetUpdateStoredProcedure(), et.GetDeleteStoredProcedure() })
    {
        if (sproc is null) continue;
        foreach (var p in sproc.Parameters.Where(p => p.ForOriginalValue == true && p.PropertyName is not null))
            if (!propNames.Contains(p.PropertyName))
                throw new InvalidOperationException($"Original-value parameter '{p.PropertyName}' on sproc '{sproc.GetStoreIdentifier().DisplayName}' is not a property of '{et.Name}'.");
    }
}

Try / catch

try { _ = ctx.Model; }
catch (InvalidOperationException ex) when (ex.Message.Contains("corresponding to the parameter"))
{
    logger.LogError("Original-value parameter references a missing property. {Msg}", ex.Message);
    throw;
}

Prevention

When it happens

Trigger: Calling .HasOriginalValueParameter(x => x.Missing) or .HasOriginalValueParameter("RenamedAway") on a sproc after the property was removed/renamed. Also when the property exists only on a sibling type and the mapping strategy (TPH/TPT/Tpc) didn't include it.

Common situations: Renaming a concurrency-token property (e.g., RowVersion) and forgetting to update the original-value parameter binding; scaffolding against stale DB metadata; refactoring a base type that previously declared the property.

Related errors


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/374a2daf61069bfd. Report an issue: GitHub.

Appendix: source

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

                            entityType.DisplayName(), resultColumn.PropertyName, storeObjectIdentifier.DisplayName()));
                default:
                    Check.DebugFail("Unexpected stored procedure type: " + storeObjectIdentifier.StoreObjectType);
                    break;
            }
        }

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

View on GitHub (pinned to 3a2006ef56)