OrchardCMS/OrchardCore · error · InvalidOperationException
Index mappings cannot be null.
Error message
Index mappings cannot be null.
What it means
ElasticsearchIndexManager builds a CreateIndexRequest from an index profile's stored metadata. The metadata.IndexMappings value is mandatory — it defines the Elasticsearch mappings for the index. When it is null the manager cannot construct a valid create-index request and throws.
Solutions
- Re-create the index from the admin UI so metadata.IndexMappings is regenerated by the index handler
- Ensure your IContentItemIndexHandler / mapping description actually populates IndexMappings before creating the index
- Delete the stale index profile metadata and rebuild: Features > Elasticsearch > rebuild the index
- Inspect the stored metadata document (ElasticsearchDocumentStorage) and fix/restore the IndexMappings value
Example fix
// before metadata.IndexMappings = null; // handler never set mappings // after var builder = new ContentItemIndexBuilder(typeOptions, _logger); await DescribeMappingsAsync(builder); // ensures IndexMappings populated before CreateIndexAsync
Defensive patterns
Strategy: validation
Validate before calling
var metadata = await _indexStore.SearchAsync<ElasticsearchIndexMetadata>(m => m.IndexName == indexProfile.IndexName);
if (metadata?.IndexMappings is null) throw new InvalidOperationException($"Index '{indexProfile.IndexName}' has no mappings; rebuild the index first"); Type guard
bool HasMappings(ElasticsearchIndexMetadata m) => m?.IndexMappings?.Mapping != null;
Try / catch
try { await indexManager.CreateAsync(indexProfile); } catch (InvalidOperationException ex) when (ex.Message.Contains("Index mappings cannot be null")) { // trigger full re-index await _indexingService.RebuildIndexAsync(indexProfile.IndexName); } Prevention
- Always build indexes through the admin UI/API so the handler populates mappings
- Don't hand-edit Elasticsearch index metadata documents
- After upgrades, rebuild legacy indexes that predate IndexMappings
When it happens
Trigger: Calling createIndexRequest/GetCreateIndexRequest for an Elasticsearch index profile whose IndexMappings was never persisted (e.g. the index handler never populated mappings, metadata was partially saved, or the index was created before the mappings step ran).
Common situations: Interrupted indexing that saved metadata without mappings; manually edited index metadata documents; upgrading indexes created by older module versions that lacked the IndexMappings field; custom Elasticsearch index handlers that do not call the mapping description.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- The index does not have a key field.
- A feature is missing a mandatory 'Id' property in the Module
- File path must be a non-empty string.
- Top level JSON element must be an object. Instead
- Can't use the numeric key
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/e597c0944b3270a8.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Elasticsearch.Core/Services/ElasticsearchIndexManager.cs:468
!s_tokenFilterGetter.TryGetValue(typeObject.ToString(), out var tokenFilterType))
{
continue;
}
RemoveTypeNode(filter.Value);
var tokenFilter = filter.Value.ToObject(tokenFilterType) as ITokenFilter;
if (tokenFilter is not null)
{
indexSettings.Analysis.TokenFilters.Add(filter.Key, tokenFilter);
}
}
}
if (metadata.IndexMappings is null)
{
throw new InvalidOperationException("Index mappings cannot be null.");
}
var createIndexRequest = new CreateIndexRequest(indexProfile.IndexFullName)
{
Settings = indexSettings,
Mappings = metadata.IndexMappings.Mapping ?? new TypeMapping(),
};
// Custom metadata to store the last indexing task id.
createIndexRequest.Mappings.Meta ??= new FluentDictionary<string, object>();
createIndexRequest.Mappings.Meta[ElasticsearchConstants.LastTaskIdMetadataKey] = 0;
return createIndexRequest;
}
private static IAnalyzer GetAnalyzer(JsonObject analyzerProperties)
{View on GitHub (pinned to 4306c0717f)