dotnet/efcore · error · NotImplementedException
Private static field assignment
Error message
Private static field assignment
What it means
Thrown by LinqToCSharpSyntaxTranslator.TranslateNonPublicMemberAssignment when assigning to a non-public member whose MemberExpression.Expression is null — i.e. assigning to a private/internal static field or property. The UnsafeAccessor translation path covers instance writes only; static private writes are unimplemented.
Solutions
- Expose a public static setter or a method that performs the assignment, and call that from the expression tree.
- Move the mutable state to an instance so the static-write path is not needed.
- If the static is effectively a constant after startup, inject it as a constant instead of writing to it.
Example fix
// before — assigns to a private static field via reflection
var field = typeof(Config).GetField("s_value",
BindingFlags.NonPublic | BindingFlags.Static)!;
var assign = Expression.Assign(
Expression.Field(null, field),
Expression.Constant(42));
// after — expose a public static setter and call it
public static void SetValue(int v) => s_value = v;
var assign = Expression.Call(
typeof(Config), nameof(Config.SetValue), null,
Expression.Constant(42)); Defensive patterns
Strategy: validation
Validate before calling
// Reject assignments to non-public static members.
using System.Linq.Expressions;
using System.Reflection;
bool AssignsToPrivateStatic(Expression e)
{
bool bad = false;
new AssignChecker(assign =>
{
if (assign.Left is MemberExpression { Expression: null, Member: var m })
{
var pub = m switch
{
FieldInfo f => f.IsPublic,
PropertyInfo p => p.SetMethod?.IsPublic ?? false,
_ => false,
};
if (!pub) bad = true;
}
}).Visit(e);
return bad;
}
class AssignChecker(Action<BinaryExpression> onAssign) : ExpressionVisitor
{
protected override Expression VisitBinary(BinaryExpression b)
{ if (b.NodeType == ExpressionType.Assign) onAssign(b); return base.VisitBinary(b); }
} Prevention
- Expose a public static setter or method for any state that must be mutated from expression trees.
- Move mutable static state into an instance so static-write paths are not needed.
- Pre-scan trees for static-target assignments before translation.
When it happens
Trigger: An expression tree assigns to a private/internal static field or static property setter through a MemberExpression with a null target (Expression.Assign(Expression.Field(null, fieldInfo), value)).
Common situations: Code that mutates private static state (configuration flags, caches) via reflection-built expression trees; provider/test fixtures that wire internal statics through Expression.Assign.
Related errors
- Private static field access
- Compound assignment of private property not yet supported
- Anonymous type creation without members
- Can't translate method
- BinaryExpression with
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/2512f1147c0fea22.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Design/Query/Internal/LinqToCSharpSyntaxTranslator.cs:1708
_g.IdentifierName(unsafeAccessorDeclaration.Identifier.Text),
Translate<ExpressionSyntax>(memberExpression.Expression));
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected virtual void TranslateNonPublicMemberAssignment(
MemberExpression memberExpression,
Expression value,
SyntaxKind assignmentKind)
{
// LINQ expression trees can directly access private members, but C# code cannot. Use the .NET [UnsafeAccessor] feature.
if (memberExpression.Expression is null)
{
throw new NotImplementedException("Private static field assignment");
}
// Get an unsafe accessor for this field/property (this internally caches and adds it to the output list of unsafe accessors)
// [UnsafeAccessor(UnsafeAccessorKind.Field, Name = "<Name>k__BackingField")]
// static extern ref int UnsafeAccessor_Foo_Name(Foo f);
var unsafeAccessorDeclaration = GetUnsafeAccessorDeclaration(
memberExpression.Member is PropertyInfo propertyInfo
? propertyInfo.SetMethod ?? throw new UnreachableException("Attempting to assign to property without setter")
: memberExpression.Member,
forWrite: true);
// The unsafe accessor declaration has been created; invoke it.
Result = memberExpression.Member switch
{
FieldInfo => AssignmentExpression(
assignmentKind,
(ExpressionSyntax)_g.InvocationExpression(View on GitHub (pinned to 3a2006ef56)