dotnet/efcore · error · InvalidOperationException
A full-text index on
Error message
A full-text index on '{entityType}' is defined over multiple properties (`{properties}`). A full-text index can only target a single property. What it means
Thrown by CosmosModelValidator.ValidateFullTextIndex when a full-text index is declared over more than one property. Azure Cosmos DB full-text indexes can target exactly one property each, so the validator rejects any composite full-text index at model validation time.
Solutions
- Split the composite full-text index into one single-property full-text index per property.
- If you need combined search across multiple fields, query each indexed property separately or project/concatenate at the application layer.
- Re-run with the corrected model to confirm validation passes.
Example fix
// before
modelBuilder.Entity<Article>()
.HasIndex(a => new { a.Title, a.Body })
.HasFullTextIndex();
// after
modelBuilder.Entity<Article>(b =>
{
b.HasIndex(a => a.Title).HasFullTextIndex();
b.HasIndex(a => a.Body).HasFullTextIndex();
}); Defensive patterns
Strategy: validation
Validate before calling
// Reject any full-text index whose property count != 1 at startup.
foreach (var et in modelBuilder.Model.GetEntityTypes())
foreach (var idx in et.GetIndexes())
if (idx.IsFullTextIndex() && idx.Properties.Count != 1)
throw new InvalidOperationException($"Full-text index on {et.DisplayName()} must target a single property."); Prevention
- Define full-text indexes one property at a time; never compose them.
- Review any .HasIndex(new { ... }) builder before chaining .HasFullTextIndex().
- Codify the single-property rule in a test that scans GetIndexes().
When it happens
Trigger: Calling HasFullTextIndex on an index whose Properties list contains 2+ properties (e.g. composing an index over (Title, Body) and marking it full-text).
Common situations: Porting a relational composite full-text index to Cosmos; combining multiple string properties into one index assuming it behaves like SQL Server's full-text catalog.
Related errors
- A full-text index is defined for
- A partition key is defined on entity type
- A vector index is defined for
- A vector index on ' ' is defined over properties ` `. A…
- Both properties ' ' and ' ' on entity type ' ' are mapped…
AI-assisted analysis of dotnet/efcore@3a2006ef56 (2026-08-11).
Data as JSON: /api/errors/5ec1c6005a197581.
Report an issue: GitHub.
Appendix: source
Thrown at src/EFCore.Cosmos/Infrastructure/Internal/CosmosModelValidator.cs:643
CosmosStrings.VectorIndexOnNonVector(
entityType.DisplayName(),
index.Properties[0].Name));
}
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject to
/// the same compatibility standards as public APIs. It may be changed or removed without notice in
/// any release. You should only use it directly in your code with extreme caution and knowing that
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
protected virtual void ValidateFullTextIndex(
IIndex index,
IDiagnosticsLogger<DbLoggerCategory.Model.Validation> logger)
{
if (index.Properties.Count > 1)
{
throw new InvalidOperationException(
CosmosStrings.CompositeFullTextIndex(
index.DeclaringEntityType.DisplayName(),
string.Join(",", index.Properties.Select(e => e.Name))));
}
if (index.Properties[0] is not IProperty firstFullTextProperty
|| firstFullTextProperty.GetIsFullTextSearchEnabled() != true)
{
throw new InvalidOperationException(
CosmosStrings.FullTextIndexOnNonFullTextProperty(
index.DeclaringEntityType.DisplayName(),
index.Properties[0].Name,
nameof(CosmosPropertyBuilderExtensions.EnableFullTextSearch)));
}
}
/// <summary>
/// This is an internal API that supports the Entity Framework Core infrastructure and not subject toView on GitHub (pinned to 3a2006ef56)