dotnet/efcore · error · NotSupportedException

Creating a container with full-text search or vector…

Error message

Creating a container with full-text search or vector properties inside a collection navigation is currently not supported using EF Core; path: '{path}'. Create the container using other means (e.g. Microsoft.Azure.Cosmos SDK).

What it means

Thrown when EF Core's Cosmos provider tries to create a container and discovers a full-text search or vector index path that lives inside an owned collection navigation (a non-unique ownership). Cosmos full-text/vector policies require a fixed JSON path, but an owned collection emits an array ('/[]'), so the path is not stable. EF refuses to emit the container policy in that case and asks you to create the container out-of-band.

Solutions

  1. Move the full-text/vector property off the owned-collection entity onto the document-root entity (or an owned singleton), so the ownership is unique and the path is stable.
  2. Create the container (with its full-text/vector indexing policy) yourself using the Microsoft.Azure.Cosmos SDK before calling EnsureCreatedAsync, so EF does not try to derive the policy.
  3. Re-model the child as a separate entity type in its own container instead of an owned collection.
  4. Remove the full-text/vector index configuration for that property if it is not strictly required.

Example fix

// before
modelBuilder.Entity<Order>().OwnsMany(o => o.Items, i =>
    i.Property(x => x.Embedding).HasVector(VectorDataType.Float32, 1536));

// after - move the vector to the document root
modelBuilder.Entity<Order>().Property(o => o.Embedding).HasVector(VectorDataType.Float32, 1536);
modelBuilder.Entity<Order>().OwnsMany(o => o.Items);
// or create the container via the Microsoft.Azure.Cosmos SDK instead of EnsureCreatedAsync.
Defensive patterns

Strategy: validation

Validate before calling

// Before calling EnsureCreatedAsync, scan the model for the unsupported pattern
var incompatible = dbContext.Model.GetEntityTypes()
    .Where(et => et.IsOwned()
        && et.FindOwnership()?.IsUnique == false
        && (et.GetDeclaredProperties().Any(p => p.IsFullText())
            || et.GetDeclaredProperties().Any(p => p.IsVector())))
    .ToList();
if (incompatible.Count != 0)
{
    // create the container via Microsoft.Azure.Cosmos SDK instead of EnsureCreatedAsync
}

Try / catch

try { await dbContext.Database.EnsureCreatedAsync(ct); }
catch (NotSupportedException ex) when (ex.Message.Contains("full-text search or vector"))
{
    // fall back to creating the container with the Azure Cosmos SDK,
    // then retry your data operations (do NOT retry EnsureCreatedAsync unchanged).
}

Prevention

When it happens

Trigger: Calling EnsureCreatedAsync/EnsureDeletedAsync (or any path that invokes CosmosClientWrapper container creation) for a model where an owned entity type reached via a collection navigation (ownership.IsUnique == false) declares a full-text index (FullTextIndex) or vector index (VectorIndex). AppendTypePathFromRoot walks from root to the owned type, and the non-unique ownership check at CosmosClientWrapper.cs:420 throws.

Common situations: Configuring a vector embedding or full-text property on a child entity that is modeled as an owned collection (e.g. a collection of owned 'Tag' or 'Embedding' objects). Migrating a relational model to Cosmos where a owned-list child happens to carry a vector/full-text column.

Related errors


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

Appendix: source

Thrown at src/EFCore.Cosmos/Storage/Internal/CosmosClientWrapper.cs:422

                var complexProperty = complexType.ComplexProperty;
                AppendTypePathFromRoot(builder, complexProperty.DeclaringType);
                AppendComplexPropertySegment(builder, complexProperty);
                break;
            }
            case IReadOnlyEntityType entityType when entityType.IsOwned():
            {
                var ownership = entityType.FindOwnership()!;
                var containingPropertyName = ownership.GetNavigation(pointsToPrincipal: false)!
                        .TargetEntityType.GetContainingPropertyName()
                    ?? throw new UnreachableException("Containing property name should not be null for owned entity types.");

                AppendTypePathFromRoot(builder, ownership.PrincipalEntityType);
                builder.Append('/');
                AppendEscapedPathSegment(builder, containingPropertyName);

                if (!ownership.IsUnique)
                {
                    throw new NotSupportedException(
                        CosmosStrings.CreatingContainerWithFullTextOrVectorOnCollectionNotSupported(builder.ToString()));
                }

                break;
            }
        }
    }

    private static void AppendComplexPropertySegment(StringBuilder builder, IReadOnlyComplexProperty complexProperty)
    {
        builder.Append('/');
        AppendEscapedPathSegment(builder, complexProperty.GetJsonPropertyName());
        if (complexProperty.IsCollection)
        {
            builder.Append("/[]");
        }
    }

View on GitHub (pinned to 3a2006ef56)