dotnet/efcore · error · InvalidOperationException

The property ' . ' is a primitive collection of a primitive…

Error message

The property '{propertyType} {type}.{property}' is a primitive collection of a primitive collection. Nested primitive collections are not yet supported with relational database providers.

What it means

ValidatePrimitiveCollection throws NestedCollectionsNotSupported when a property is a primitive collection whose element type mapping itself has a non-null ElementTypeMapping — i.e. a collection of collections (e.g. List<List<int>>, or int[][]). The relational provider can map a single-level primitive collection (to JSON or a native array column), but nested primitive collections are not yet implemented.

Solutions

  1. Flatten the nested collection into a single-level collection of a wrapper type (e.g. List<MatrixCell> with Row/Col/Value), mapped as a complex collection ToJson.
  2. Store the nested data as a string column with a HasConversion that serializes to JSON manually.
  3. Model the inner collection as a separate owned/JSON entity relationship rather than a primitive collection.

Example fix

// before
public class Matrix { public List<List<double>> Cells { get; set; } } // throws

// after — flatten to a complex collection
public class MatrixCell { public int Row { get; set; } public int Col { get; set; } public double Value { get; set; } }
public class Matrix { public List<MatrixCell> Cells { get; set; } = new(); }
modelBuilder.Entity<Matrix>().OwnsMany(m => m.Cells, c => c.ToJson());
Defensive patterns

Strategy: validation

Validate before calling

if (property is { IsPrimitiveCollection: true }
    && property.GetTypeMapping().ElementTypeMapping?.ElementTypeMapping != null)
    throw new InvalidOperationException("Nested primitive collections are not supported.");

Type guard

static bool IsNestedPrimitiveCollection(IProperty p)
    => p is { IsPrimitiveCollection: true }
       && p.GetTypeMapping().ElementTypeMapping?.ElementTypeMapping != null;

Prevention

When it happens

Trigger: Declaring a property whose CLR type is IEnumerable<IEnumerable<T>> (or jagged arrays) on an entity. property.GetTypeMapping().ElementTypeMapping?.ElementTypeMapping != null is the nested-collection signature. Fires for any relational provider because the SQL generation cannot express nesting yet.

Common situations: Domain models with matrix/grid data (List<List<double>>); porting a model that relied on JSON serialization to store nested arrays; upgrading from a model that stored nested collections as opaque JSON strings via value converters.

Related errors


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

Appendix: source

Thrown at src/EFCore.Relational/Infrastructure/RelationalModelValidator.cs:254

        ValidateDefaultValuesOnKey(key, logger);
        ValidateValueGeneration(key, logger);
    }

    /// <summary>
    ///     Validates a primitive collection property.
    /// </summary>
    /// <param name="property">The property to validate.</param>
    /// <param name="logger">The logger to use.</param>
    protected override void ValidatePrimitiveCollection(
        IProperty property,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        base.ValidatePrimitiveCollection(property, logger);

        if (property is { IsPrimitiveCollection: true }
            && property.GetTypeMapping().ElementTypeMapping?.ElementTypeMapping != null)
        {
            throw new InvalidOperationException(
                RelationalStrings.NestedCollectionsNotSupported(
                    property.ClrType.ShortDisplayName(), property.DeclaringType.DisplayName(), property.Name));
        }
    }

    /// <inheritdoc />
    protected override void ValidatePropertyMapping(
        IComplexProperty complexProperty,
        IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
    {
        base.ValidatePropertyMapping(complexProperty, logger);

        if (complexProperty.IsCollection && !complexProperty.ComplexType.IsMappedToJson())
        {
            throw new InvalidOperationException(
                RelationalStrings.ComplexCollectionNotMappedToJson(
                    complexProperty.DeclaringType.DisplayName(), complexProperty.Name));
        }

View on GitHub (pinned to 3a2006ef56)