dotnet/efcore · error · InvalidOperationException
'VisitChildren' must be overridden in the class deriving fro
Error message
'VisitChildren' must be overridden in the class deriving from 'SqlExpression'.
What it means
The abstract SqlExpression.VisitChildren intentionally throws InvalidOperationException to force every concrete subclass to override VisitChildren (so expression-tree rewriting visits child SqlExpressions correctly). Hitting this means a SqlExpression subclass was visited without overriding the method.
Source
Thrown at src/EFCore.Cosmos/Query/Internal/Expressions/SqlExpression.cs:41
/// </summary>
public override Type Type { get; } = type;
/// <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>
public virtual CoreTypeMapping? TypeMapping { get; } = typeMapping;
/// <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 override Expression VisitChildren(ExpressionVisitor visitor)
=> throw new InvalidOperationException(CosmosStrings.VisitChildrenMustBeOverridden);
/// <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>
public sealed override ExpressionType NodeType
=> ExpressionType.Extension;
/// <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 abstract void Print(ExpressionPrinter expressionPrinter);
View on GitHub (pinned to dbf9771522)
Solutions
- Override VisitChildren in every custom SqlExpression subclass, returning a new instance when children change (and `this` when they don't).
- Ensure internal expression types you depend on are from a consistent EF Core build (no mixed versions).
- If you are an end user not subclassing SqlExpression, report it as a provider bug.
Example fix
// before
class MyExpr : SqlExpression { /* no VisitChildren override -> throws on visit */ }
// after
protected override Expression VisitChildren(ExpressionVisitor visitor)
{
var child = (SqlExpression)visitor.Visit(Child);
return child == Child ? this : new MyExpr(child);
} Defensive patterns
Strategy: type-guard
Validate before calling
// For custom SqlExpression subclasses, assert VisitChildren is overridden at startup.
foreach (var t in Assembly.GetExecutingAssembly().GetTypes()
.Where(t => typeof(SqlExpression).IsAssignableFrom(t) && !t.IsAbstract))
if (t.GetMethod(nameof(Expression.VisitChildren),
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
Type.DefaultBinder, new[] { typeof(ExpressionVisitor) }, null)?.DeclaringType != t)
throw new InvalidOperationException($"{t} must override VisitChildren."); Type guard
static bool OverridesVisitChildren(Type t)
=> t.GetMethod(nameof(Expression.VisitChildren),
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public,
Type.DefaultBinder, new[] { typeof(ExpressionVisitor) }, null)?.DeclaringType == t; Try / catch
try { visitor.Visit(mySqlExpression); }
catch (InvalidOperationException ex) when (ex.Message.Contains("VisitChildren"))
{ /* add VisitChildren override to the custom SqlExpression subclass */ } Prevention
- Always override VisitChildren in custom SqlExpression subclasses.
- Add a reflection-based startup test verifying all SqlExpression subclasses override it.
When it happens
Trigger: A custom SqlExpression subclass that did not override VisitChildren is passed through an ExpressionVisitor; or an internal expression type lost its override after a refactor.
Common situations: Writing a custom Cosmos query extension that introduces a new SqlExpression-derived type; provider regression after upgrades.
Related errors
- Calling '{visitMethodName}' is not allowed. Visit the expres
- Exactly one of '{param1}' or '{param2}' must be set.
- Unsupported operator '{nodeType}' specified for expression o
- Unsupported operator '{nodeType}' specified for expression o
- Unsupported operator '{nodeType}' specified for expression o
AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06).
Data as JSON: /api/errors/345fb1eb79eddb64.
Report an issue: GitHub.