dotnet/efcore · error · InvalidOperationException
The property '{entityType}.{property}' has a value generator
Error message
The property '{entityType}.{property}' has a value generator configured. Use '{method}' to configure the value generator factory type. What it means
Thrown in CSharpRuntimeModelCodeGenerator.Create(IProperty) (line 1088, resource CompiledModelValueGenerator) when generating a compiled model for a property that has a value generator configured via a factory instance rather than a factory type. Compiled models can only encode a value-generator factory type, so when a property has GetValueGeneratorFactory() != null but no ValueGeneratorFactoryType annotation, generation aborts and points you to HasValueGeneratorFactory.
Source
Thrown at src/EFCore.Design/Scaffolding/Internal/CSharpRuntimeModelCodeGenerator.cs:1088
.Append(_code.UnknownLiteral(providerValue))
.AppendLine(");")
.AppendLine();
}
}
}
private void Create(
IProperty property,
Dictionary<MemberInfo, QualifiedName>? memberAccessReplacements,
CSharpRuntimeAnnotationCodeGeneratorParameters parameters)
{
var variableName = _code.Identifier(property.Name, property, parameters.ScopeObjects, capitalize: false);
var valueGeneratorFactoryType = (Type?)property[CoreAnnotationNames.ValueGeneratorFactoryType];
if (valueGeneratorFactoryType == null
&& property.GetValueGeneratorFactory() != null)
{
throw new InvalidOperationException(
DesignStrings.CompiledModelValueGenerator(
property.DeclaringType.ShortName(), property.Name, nameof(PropertyBuilder.HasValueGeneratorFactory)));
}
var mainBuilder = parameters.MainBuilder;
mainBuilder
.Append("var ").Append(variableName).Append(" = ").Append(parameters.TargetName).AppendLine(".AddProperty(")
.IncrementIndent()
.Append(_code.Literal(property.Name));
GeneratePropertyBaseParameters(property, parameters);
if (property.IsNullable)
{
mainBuilder.AppendLine(",")
.Append("nullable: ")
.Append(_code.Literal(true));
}View on GitHub (pinned to dbf9771522)
Solutions
- Replace HasValueGenerator(instance factory) with HasValueGeneratorFactory(typeof(MyGenerator)) so the compiled model can encode the type.
- Ensure your value generator has a parameterless constructor so it can be activated from the factory type.
- Re-run compiled-model generation after the switch.
- If an instance factory is mandatory, exclude the property/entity from compiled-model generation.
Example fix
// before: instance-based value generator blocks compiled models
modelBuilder.Entity<Order>()
.Property(o => o.Number)
.HasValueGenerator(() => new OrderNumberGenerator());
// after: type-based factory the compiled model can encode
modelBuilder.Entity<Order>()
.Property(o => o.Number)
.HasValueGeneratorFactory<OrderNumberGenerator>(); Defensive patterns
Strategy: validation
Validate before calling
// Detect instance-based value generators before compiled-model generation
foreach (var et in model.GetEntityTypes())
foreach (var p in et.GetProperties())
if (p[CoreAnnotationNames.ValueGeneratorFactoryType] is null
&& p.GetValueGeneratorFactory() is not null)
{ /* switch to HasValueGeneratorFactory<T>() */ } Try / catch
try { /* generate compiled model */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("value generator"))
{ /* switch HasValueGenerator -> HasValueGeneratorFactory<T>(), then retry */ } Prevention
- Prefer HasValueGeneratorFactory<T>() over instance-based HasValueGenerator when using compiled models.
- Ensure value generators have parameterless constructors.
When it happens
Trigger: Running compiled-model generation for a property configured with HasValueGenerator (an instance-based factory) rather than HasValueGeneratorFactory (a type-based factory). The check `valueGeneratorFactoryType == null && property.GetValueGeneratorFactory() != null` is true and throws CompiledModelValueGenerator(entityType, property, nameof(PropertyBuilder.HasValueGeneratorFactory)).
Common situations: Configuring a property with HasValueGenerator(() => new MyGenerator()) and then enabling compiled models. Instance-based generators cannot be serialized into the compiled model source. Switching an existing model to compiled models reveals these instance-based configurations.
Related errors
- Compound assignment not supported yet.
- The entity type '{entityType}' has a custom constructor bind
- The entity type '{entityType}' has a query filter configured
- No files were generated in directory '{outputDirectoryName}'
- You cannot add a migration with the name 'Migration'.
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/6d30b499347db8fb.
Report an issue: GitHub.