dotnet/efcore · error · InvalidOperationException

Cosmos automatic-indexing configuration was set on entity ty

Error message

Cosmos automatic-indexing configuration was set on entity type '{entityType}', but it must be configured on the document-root entity type '{rootEntityType}' instead. Automatic-indexing settings apply to the container as a whole and are inherited by derived types.

What it means

Thrown by ValidateContainerIndexing when a derived entity type (one whose BaseType is set) directly carries the AutomaticIndexingEnabled or AutomaticIndexingExceptions annotation. The validator explicitly checks these annotations on non-root types and rejects them, because automatic indexing is a container-wide policy that must live on the document root and is inherited by derived types.

Source

Thrown at src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs:330

        ValidateContainerIndexing(mappedTypes, container);
    }

    private static void ValidateContainerIndexing(IReadOnlyList<IEntityType> mappedTypes, string container)
    {
        IEntityType? automaticIndexingOwner = null;
        bool? automaticIndexingEnabled = null;
        IReadOnlyList<string>? automaticIndexingExceptions = null;

        foreach (var entityType in mappedTypes)
        {
            // Only document-root entity types can carry automatic-indexing configuration.
            // The same setting must apply to every entity type in a shared container.
            if (entityType.BaseType is not null
                && (entityType.FindAnnotation(CosmosAnnotationNames.AutomaticIndexingEnabled) is not null
                    || entityType.FindAnnotation(CosmosAnnotationNames.AutomaticIndexingExceptions) is not null))
            {
                throw new InvalidOperationException(
                    CosmosStrings.AutomaticIndexingNotOnRoot(
                        entityType.DisplayName(),
                        entityType.GetRootType().DisplayName()));
            }

            var currentEnabled = entityType.BaseType is null
                ? (bool?)entityType.FindAnnotation(CosmosAnnotationNames.AutomaticIndexingEnabled)?.Value
                : null;
            var currentExceptions = entityType.BaseType is null
                ? (IReadOnlyList<string>?)entityType.FindAnnotation(CosmosAnnotationNames.AutomaticIndexingExceptions)?.Value
                : null;
            if (currentEnabled is not null || currentExceptions is not null)
            {
                if (automaticIndexingOwner is null)
                {
                    automaticIndexingOwner = entityType;
                    automaticIndexingEnabled = currentEnabled;
                    automaticIndexingExceptions = currentExceptions;

View on GitHub (pinned to dbf9771522)

Solutions

  1. Move the HasAutomaticIndexing call to the root entity type of the hierarchy.
  2. Guard your shared configuration helper with `if (entityType.BaseType == null)` before applying automatic-indexing config.
  3. Remove the call from the derived type and re-apply it on the root via the root's EntityTypeBuilder.

Example fix

// before
modelBuilder.Entity<Manager>().HasAutomaticIndexing(true); // Manager derives from Employee

// after
modelBuilder.Entity<Employee>().HasAutomaticIndexing(true); // applied on the root
Defensive patterns

Strategy: validation

Validate before calling

// Guard your shared config helper so automatic indexing is only set on roots:
static void ConfigureCosmos<T>(EntityTypeBuilder<T> et) where T : class
{
    if (et.Metadata.BaseType is null)
        et.HasAutomaticIndexing(true);
}
// In a test:
using var ctx = new MyContext();
foreach (var e in ctx.Model.GetEntityTypes().Where(t => t.BaseType is not null))
{
    Debug.Assert(e.FindAnnotation("Cosmos:AutomaticIndexingEnabled") is null
        && e.FindAnnotation("Cosmos:AutomaticIndexingExceptions") is null,
        $"{e.Name} must not set automatic indexing (not a root)");
}

Type guard

// Type-guard-style helper: only apply container-level config to document roots.
static bool IsDocumentRoot<TEntity>(EntityTypeBuilder<TEntity> et) where T : class
    => et.Metadata.BaseType is null && et.Metadata.IsDocumentRoot();

Try / catch

try { ctx.Model.GetModel(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("automatic-indexing configuration was set"))
{
    logger.LogError(ex, "HasAutomaticIndexing called on a derived type");
    throw;
}

Prevention

When it happens

Trigger: Calling HasAutomaticIndexing(...) (or chained .Except(...)) on an EntityTypeBuilder whose entity is a derived type in a TPH/inheritance hierarchy, during model validation.

Common situations: Applying a shared configuration routine to every entity in an inheritance hierarchy without skipping derived types; configuring indexing per-entity thinking it is per-type; recent upgrade that introduced container-level indexing config.

Related errors


AI-assisted analysis of dotnet/efcore@dbf9771522 (2026-08-06). Data as JSON: /api/errors/f70bf47d9deb3249. Report an issue: GitHub.