OrchardCMS/OrchardCore · error · InvalidOperationException

An ambiguous index has been found.

Error message

An ambiguous index has been found.

What it means

When building the ContentItems GraphQL query, aliases collected for the same index (same Index key) must agree on IndexType. If two aliased paths map to the same index name but different index types, the query would produce contradictory table bindings, so an InvalidOperationException('An ambiguous index has been found.') is thrown in FilterWhereArgumentsAsync.

Solutions

  1. Rename one of the conflicting indexes so each index name maps to exactly one index type.
  2. Change the GraphQL query to use a single alias/path for that index.
  3. Align the IndexType of the duplicated profiles in the indexing settings.

Example fix

// before
// two profiles: "BlogPostIndex" (type Sql) and "BlogPostIndex" (type Lucene)
// after
// rename one to "BlogPostSqlIndex" or remove the duplicate profile
Defensive patterns

Strategy: validation

Validate before calling

// pre-check before building the query: ensure each index name maps to one index type
var dupes = aliases.GroupBy(a => a.Index).Where(g => g.Select(x => x.IndexType).Distinct().Count() > 1).ToList();
if (dupes.Any()) throw new InvalidOperationException($"Ambiguous indexes: {string.Join(",", dupes.Select(d => d.Key))}");

Try / catch

try { var result = await query.FilterWhereArgumentsAsync(...); }
catch (InvalidOperationException ex) when (ex.Message == "An ambiguous index has been found.") { _logger.LogError(ex, "Duplicate index name with differing index types in GraphQL where-input"); throw; }

Prevention

When it happens

Trigger: A GraphQL where-input uses two aliased paths (e.g. two fields or two index profiles) whose resolved alias.Index is identical but whose IndexType differs — typically two index profiles with the same index name configured with different index types (SQL vs Lucene, or different profile types).

Common situations: Two ContentIndex profiles named the same for different providers; custom index handlers emitting colliding index names; merging where-clauses across modules that both register aliases for the same index name.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13). Data as JSON: /api/errors/c5265f3a79835fc5. Report an issue: GitHub.

Appendix: source

Thrown at src/OrchardCore/OrchardCore.ContentManagement.GraphQL/Queries/ContentItemsFieldType.cs:163

        predicateQuery.CreateTableAlias(nameof(ContentItemIndex), defaultTableAlias);

        // Add all provided table alias to the current predicate query.
        var providers = fieldContext.RequestServices.GetServices<IIndexAliasProvider>();
        var indexes = new Dictionary<string, IndexAlias>(StringComparer.OrdinalIgnoreCase);
        var indexAliases = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

        foreach (var aliasProvider in providers)
        {
            foreach (var alias in await aliasProvider.GetAliasesAsync())
            {
                predicateQuery.CreateAlias(alias.Alias, alias.Index, alias.IsPartial);
                if (indexAliases.Add(alias.Alias))
                {
                    if (!indexes.TryAdd(alias.Index, alias))
                    {
                        if (indexes[alias.Index].IndexType != alias.IndexType)
                        {
                            throw new InvalidOperationException("An ambiguous index has been found.");
                        }
                    }
                }
            }
        }

        var expressions = Expression.Conjunction();

        var whereInput = (IFilterInputObjectGraphType)fieldContext.FieldDefinition.Arguments.FirstOrDefault(x => x.Name == "where")?.ResolvedType;

        BuildWhereExpressions(where, expressions, null, whereInput, indexAliases);

        expressions.SearchUsedAlias(predicateQuery);

        // Add all Indexes that were used in the predicate query.
        IQuery<ContentItem> contentQuery = query;
        foreach (var usedAlias in predicateQuery.GetUsedAliases())
        {

View on GitHub (pinned to 4306c0717f)