dotnet/efcore · error · InvalidOperationException

The exception list configured for Cosmos automatic indexing

Error message

The exception list configured for Cosmos automatic indexing on container '{container}' differs between entity types '{entityType1}' and '{entityType2}'. All entity types mapped to the same container must agree on the automatic-indexing exception list.

What it means

Thrown by ValidateContainerIndexing when two document-root entity types in the same container agree that automatic indexing is enabled but their exception (excluded-path) lists differ. The validator compares the AutomaticIndexingExceptions lists for null-ness and element-wise equality (ordinal); only compared when automatic indexing is enabled.

Source

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

                    // an explicit 'true' when comparing across entity types in the same container.
                    if ((currentEnabled ?? true) != (automaticIndexingEnabled ?? true))
                    {
                        throw new InvalidOperationException(
                            CosmosStrings.InconsistentAutomaticIndexingEnabled(
                                container,
                                automaticIndexingOwner.DisplayName(),
                                entityType.DisplayName()));
                    }

                    // Exceptions only affect the indexing policy when automatic indexing is enabled, so don't compare
                    // them when it is disabled.
                    if ((automaticIndexingEnabled ?? true)
                        && ((currentExceptions is null) != (automaticIndexingExceptions is null)
                            || (currentExceptions is not null
                                && automaticIndexingExceptions is not null
                                && !currentExceptions.SequenceEqual(automaticIndexingExceptions, StringComparer.Ordinal))))
                    {
                        throw new InvalidOperationException(
                            CosmosStrings.InconsistentAutomaticIndexing(
                                container,
                                automaticIndexingOwner.DisplayName(),
                                entityType.DisplayName()));
                    }
                }
            }

            // Walk the full owned/complex tree to surface every HasIndex declared in this container.
            // Vector and full-text indexes are allowed to traverse owned types; only regular indexes are
            // rejected
            foreach (var (declaringEntityType, index) in EnumerateContainerIndexes(entityType))
            {
                if (!declaringEntityType.IsDocumentRoot()
                    && index.GetVectorIndexType() == null
                    && index.IsFullTextIndex() != true)
                {
                    throw new InvalidOperationException(

View on GitHub (pinned to dbf9771522)

Solutions

  1. Make the excluded-path list identical (same set, same order) on every root entity in the container.
  2. Consolidate automatic-indexing configuration onto one root entity and remove it from the others.
  3. Centralize the exception list in a constant and apply it uniformly.

Example fix

// before
modelBuilder.Entity<A>().ToContainer("shared").HasAutomaticIndexing(true).Except("/temp/*");
modelBuilder.Entity<B>().ToContainer("shared").HasAutomaticIndexing(true).Except("/cache/*");

// after
string[] excluded = ["/temp/*", "/cache/*"];
var aBuilder = modelBuilder.Entity<A>().ToContainer("shared").HasAutomaticIndexing(true);
foreach (var p in excluded) aBuilder.Except(p);
var bBuilder = modelBuilder.Entity<B>().ToContainer("shared").HasAutomaticIndexing(true);
foreach (var p in excluded) bBuilder.Except(p);
Defensive patterns

Strategy: validation

Validate before calling

using var ctx = new MyContext();
foreach (var grp in ctx.Model.GetEntityTypes()
    .Where(e => e.FindPrimaryKey() != null && e.GetContainer() != null && e.BaseType == null)
    .GroupBy(e => e.GetContainer()))
{
    var lists = grp.Select(e => (e.GetAutomaticIndexingEnabled() ?? true)
        ? (e.GetAutomaticIndexingExceptions() ?? Array.Empty<string>()).OrderBy(s => s).ToArray()
        : Array.Empty<string>())
        .Select(a => string.Join(",", a)).Distinct().ToList();
    Debug.Assert(lists.Count <= 1, $"Container {grp.Key} has differing exception lists");
}

Try / catch

try { ctx.Model.GetModel(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("exception list configured for Cosmos automatic indexing"))
{
    logger.LogError(ex, "Automatic-indexing exception list mismatch in shared container");
    throw;
}

Prevention

When it happens

Trigger: Calling .HasAutomaticIndexing(true).Except("/a/*") on one root and .HasAutomaticIndexing(true).Except("/b/*") (or no Except) on another root mapped to the same container.

Common situations: Per-entity tuning of excluded write paths without realizing the exclusion list is container-wide; incrementally adding exclusions on new entities; refactoring an entity into a shared container with a different exclusion set.

Related errors


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