dotnet/efcore · error · InvalidOperationException

The property ' . ' is mapped to an output parameter of the…

Error message

The property '{entityType}.{property}' is mapped to an output parameter of the stored procedure '{sproc}', but it is not configured as store-generated. Either configure it as store-generated or don't configure the parameter as output.

What it means

Thrown when an insert/update sproc parameter is configured as Output (or InputOutput / ReturnValue) and bound to a property that is NOT store-generated. The validator only allows non-input parameters for properties in the storeGeneratedProperties set; failing to remove the property from that set means the database will not supply a value, so an output parameter is meaningless and the model is rejected.

Solutions

  1. Configure the property as store-generated: builder.Property(p => p.Foo).ValueGeneratedOnAdd() / .HasDefaultValueSql(...) / .HasComputedColumnSql(...) so it belongs in storeGeneratedProperties.
  2. If the property is not store-generated, change the parameter to Input: use HasParameter(p => p.Foo) instead of HasOutputParameter(p => p.Foo).
  3. Remove the parameter mapping entirely if the sproc does not actually populate it.

Example fix

// before
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp => sp.HasOutputParameter(o => o.CustomerName)); // not store-generated

// after
entityType.InsertUsingStoredProcedure("InsertOrder",
    sp => sp.HasParameter(o => o.CustomerName));
// or, if the DB really populates it:
// builder.Property(o => o.CustomerName).HasDefaultValueSql("...");
Defensive patterns

Strategy: validation

Validate before calling

foreach (var et in model.GetEntityTypes())
{
    foreach (var sproc in new[] { et.GetInsertStoredProcedure(), et.GetUpdateStoredProcedure() })
    {
        if (sproc == null) continue;
        foreach (var p in sproc.Parameters.Where(p => p.Direction != System.Data.ParameterDirection.Input))
        {
            if (p.PropertyName is string name)
            {
                var prop = et.FindProperty(name);
                if (prop?.ValueGenerated == Microsoft.EntityFrameworkCore.Metadata.ValueGenerated.Never
                    && prop?.GetDefaultValue() == null
                    && prop?.GetDefaultValueSql() == null
                    && prop?.GetComputedColumnSql() == null)
                {
                    Console.WriteLine($"{et.Name}.{name} is output on {sproc.Name} but not store-generated.");
                }
            }
        }
    }
}

Prevention

When it happens

Trigger: .HasOutputParameter(p => p.NonGeneratedColumn) on an Insert/Update sproc where NonGeneratedColumn has no ValueGenerated configuration and no database default/computed setting. The Direction is set to Output or InputOutput on a property EF considers user-supplied.

Common situations: Marking a regular property as an output parameter expecting the sproc to echo it back; confusing HasOutputParameter with HasParameter; flipping a column from database-generated to client-generated without updating the sproc mapping.

Related errors


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

Appendix: source

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

            }

            switch (storeObjectIdentifier.StoreObjectType)
            {
                case StoreObjectType.InsertStoredProcedure:
                case StoreObjectType.UpdateStoredProcedure:
                    if (parameter.Direction != ParameterDirection.Input
                        && !storeGeneratedProperties.Remove(property!.Name))
                    {
                        if (sproc.Parameters.Any(p => p.PropertyName == property.Name
                                && p.ForOriginalValue != parameter.ForOriginalValue
                                && p.Direction != ParameterDirection.Input))
                        {
                            throw new InvalidOperationException(
                                RelationalStrings.StoredProcedureOutputParameterConflict(
                                    entityType.DisplayName(), parameter.PropertyName, storeObjectIdentifier.DisplayName()));
                        }

                        throw new InvalidOperationException(
                            RelationalStrings.StoredProcedureOutputParameterNotGenerated(
                                entityType.DisplayName(), parameter.PropertyName, storeObjectIdentifier.DisplayName()));
                    }

                    break;
                case StoreObjectType.DeleteStoredProcedure:
                    if (!property!.IsPrimaryKey()
                        && !property.IsConcurrencyToken)
                    {
                        throw new InvalidOperationException(
                            RelationalStrings.StoredProcedureDeleteNonKeyProperty(
                                entityType.DisplayName(), parameter.PropertyName, storeObjectIdentifier.DisplayName()));
                    }

                    break;
                default:
                    Check.DebugFail("Unexpected stored procedure type: " + storeObjectIdentifier.StoreObjectType);
                    break;

View on GitHub (pinned to 3a2006ef56)