dotnet/efcore · error · InvalidOperationException
Property '{property}' on entity type '{entityType}' is mappe
Error message
Property '{property}' on entity type '{entityType}' is mapped without a CLR property. 'UseChangeTrackingProxies' requires all entity types to be public, unsealed, have virtual properties, and have a public or protected constructor. 'UseLazyLoadingProxies' requires only the navigation properties be virtual. What it means
With UseChangeTrackingProxies enabled, a navigation that is not a shadow property but has no PropertyInfo (navigationBase.PropertyInfo == null) throws FieldProperty (ProxyBindingRewriter.cs:84-88). Change-tracking proxies must override the property setter, so a field-only navigation without a CLR property cannot be proxied.
Source
Thrown at src/EFCore.Proxies/Proxies/Internal/ProxyBindingRewriter.cs:86
{
continue;
}
if (clrType.IsSealed)
{
throw new InvalidOperationException(ProxiesStrings.ItsASeal(entityType.DisplayName()));
}
foreach (var navigationBase in entityType.GetDeclaredNavigations()
.Concat<IConventionNavigationBase>(entityType.GetDeclaredSkipNavigations()))
{
if (!navigationBase.IsShadowProperty())
{
if (_options.UseChangeTrackingProxies)
{
if (navigationBase.PropertyInfo == null)
{
throw new InvalidOperationException(
ProxiesStrings.FieldProperty(navigationBase.Name, entityType.DisplayName()));
}
if (navigationBase.PropertyInfo.SetMethod?.IsReallyVirtual() == false)
{
throw new InvalidOperationException(
ProxiesStrings.NonVirtualProperty(navigationBase.Name, entityType.DisplayName()));
}
}
if (_options.UseLazyLoadingProxies
&& navigationBase.LazyLoadingEnabled)
{
if (navigationBase.PropertyInfo == null
|| !navigationBase.PropertyInfo.GetMethod!.IsReallyVirtual())
{
if (!_options.IgnoreNonVirtualNavigations
&& navigationBase is not INavigation { ForeignKey.IsOwnership: true })View on GitHub (pinned to dbf9771522)
Solutions
- Expose a CLR property (with virtual setter) for the navigation instead of a field-only mapping.
- Do not use field-only access mode for navigations when change-tracking proxies are enabled.
- Stop using change-tracking proxies if field-only navigation mapping is required.
Example fix
// before
private List<Post> _posts = new();
public IEnumerable<Post> Posts => _posts; // field-only, no setter property
// after
public virtual ICollection<Post> Posts { get; set; } = new List<Post>(); Defensive patterns
Strategy: validation
Validate before calling
// Verify each navigation has a CLR property before enabling change-tracking proxies:
foreach (var et in modelBuilder.Model.GetEntityTypes())
foreach (var nav in et.GetNavigations())
{
if (!nav.IsShadowProperty() && nav.PropertyInfo is null)
throw new InvalidOperationException($"{et.Name}.{nav.Name} has no CLR property; cannot use change-tracking proxies.");
} Prevention
- Expose CLR properties (with virtual setters) for all navigations when using change-tracking proxies.
- Avoid field-only navigation mappings with change-tracking proxies.
- Audit navigation access modes before enabling proxies.
When it happens
Trigger: Enabling UseChangeTrackingProxies with a navigation mapped without a CLR property (field-only access or a navigation exposed only via a field/getter).
Common situations: Using UsePropertyAccessMode.Field or field-only navigation conventions together with change-tracking proxies.
Related errors
- Property '{entityType}.{property}' is not virtual. 'UseChang
- Entity type '{entityType}' is sealed. 'UseChangeTrackingProx
- The type '{dictionaryType}' used for shared entity type '{en
- The mapped indexer property on entity type '{entityType}' is
- Including navigation '{navigation}' is not supported as the
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/fa2d6159910ad45f.
Report an issue: GitHub.