dotnet/efcore · error · InvalidOperationException
The JSON query expression for '{structuralType}' has no unde
Error message
The JSON query expression for '{structuralType}' has no underlying column. What it means
Thrown by JsonQueryExpression.GetJsonElement when the expression's JsonColumn has no underlying ColumnExpression (Column is null). This means the JSON query expression was constructed for a synthetic or computed JSON source (e.g., OPENJSON/json_each expansion) rather than a real table column, and a concrete column-backed JSON element was expected.
Source
Thrown at src/EFCore.Relational/Query/JsonQueryExpression.cs:310
return Update(jsonColumn, newKeyPropertyMap);
}
/// <summary>
/// Finds the <see cref="IRelationalJsonElement" /> for the given property/navigation/complex property within the
/// JSON column referenced by this expression by matching <see cref="JsonColumn" />'s underlying
/// <see cref="ColumnExpression.Column" /> against <see cref="IRelationalJsonElement.ContainingColumn" />. This
/// disambiguates entity-splitting, TPT and TPC scenarios where the same property has multiple JSON element
/// mappings — one per concrete table.
/// <see cref="IRelationalJsonElement.PropertyName" /> may be <see langword="null" /> for shadow keys that have
/// no JSON representation; callers iterating over <see cref="ITypeBase.GetProperties" /> must handle that case
/// and skip them.
/// </summary>
/// <param name="propertyBase">The property, navigation or complex property to look up.</param>
/// <returns>The JSON element mapping for <paramref name="propertyBase" />.</returns>
public virtual IRelationalJsonElement GetJsonElement(IPropertyBase propertyBase)
{
var column = JsonColumn.Column
?? throw new InvalidOperationException(
RelationalStrings.JsonQueryExpressionWithoutUnderlyingColumn(StructuralType.DisplayName()));
return FindJsonElement(propertyBase)
?? throw new InvalidOperationException(
RelationalStrings.JsonElementMappingNotFound(propertyBase.DeclaringType.DisplayName(), propertyBase.Name, column.Name));
}
/// <summary>
/// Finds the <see cref="IRelationalJsonElement" /> for the given property/navigation/complex property within the
/// JSON column referenced by this expression by matching <see cref="JsonColumn" />'s underlying
/// <see cref="ColumnExpression.Column" /> against <see cref="IRelationalJsonElement.ContainingColumn" />, or returns
/// <see langword="null" /> if no such element exists (including when <see cref="JsonColumn" /> has no underlying
/// <see cref="ColumnExpression.Column" />, e.g. for synthetic JSON expansions over OPENJSON / json_each, or for
/// iterated properties such as shadow keys that have no JSON representation).
/// </summary>
/// <param name="propertyBase">The property, navigation or complex property to look up.</param>
/// <returns>The JSON element mapping for <paramref name="propertyBase" />, or <see langword="null" /> if not found.</returns>
public virtual IRelationalJsonElement? FindJsonElement(IPropertyBase propertyBase)
{View on GitHub (pinned to 3a2006ef56)
Solutions
- Ensure JSON-mapped entities are queried directly from their table (not from a view, CTE, or subquery that obscures the column).
- If using raw SQL with JSON, ensure the JSON column is selected from the actual table.
- Check that your provider version supports the JSON query pattern you're using.
- File an issue at https://github.com/dotnet/efcore if this occurs with a standard table-mapped JSON entity.
Example fix
// before — querying JSON entity through a view or subquery that loses the column binding
var query = context.CustomerViews // a view, not the base table
.Select(c => c.Addresses);
// after — query from the base table directly
var query = context.Customers
.Select(c => c.Addresses); Defensive patterns
Strategy: try-catch
Try / catch
try
{
var result = await context.Customers.Select(c => c.Addresses).ToListAsync();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("no underlying column"))
{
logger.LogError(ex, "JSON query expression has no column backing — query from base table, not view/subquery");
throw;
} Prevention
- Query JSON-mapped entities directly from their base table, not from views or CTEs.
- Ensure JSON columns are physical table columns, not computed or derived.
- Test JSON queries in integration tests against the real schema.
- Report synthetic-column issues to the EF Core team with the provider and query details.
When it happens
Trigger: Internal query pipeline calls GetJsonElement on a JsonQueryExpression whose JsonColumn.Column is null. This occurs with provider-specific synthetic JSON expansions (SQL Server OPENJSON, SQLite json_each) or when the JSON column expression is a computed/projection column rather than a base table column.
Common situations: Using JSON queries against views or derived tables where the JSON column is computed rather than a physical column. Provider-specific JSON expansion paths (OPENJSON) that create synthetic JSON columns. An EF Core internal bug where a JsonQueryExpression is used before its column binding is established.
Related errors
- Unable to bind '{memberType}.{member}' to an entity projecti
- No JSON element mapping was found for '{structuralType}.{nam
- Both properties '{property1}' and '{property2}' on entity ty
- The JSON property name should only be configured on nested o
- The property '{property}' on type '{type}' is mapped to a JS
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/e3458af59d9488ac.
Report an issue: GitHub.