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

  1. Ensure JSON-mapped entities are queried directly from their table (not from a view, CTE, or subquery that obscures the column).
  2. If using raw SQL with JSON, ensure the JSON column is selected from the actual table.
  3. Check that your provider version supports the JSON query pattern you're using.
  4. 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

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


AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11). Data as JSON: /api/errors/e3458af59d9488ac. Report an issue: GitHub.