elasticsearch-net icon indicating copy to clipboard operation
elasticsearch-net copied to clipboard

Elastic.Transport.UnexpectedTransportException: Index name is null for the given type and no default index is set (BulkDeleteOperation)

Open yansklyarenko opened this issue 7 months ago • 2 comments

Elastic.Clients.Elasticsearch version: 8.11.0

Elasticsearch version: 8.2.2

.NET runtime version: net7.0

Operating system version: Windows 10

Description of the problem including expected versus actual behavior: Prerequisites: there's an index "my-test-index" containing a document with id equals "1".

Consider the following code:

var deleteOperation = new BulkDeleteOperation<IReadOnlyDictionary<string, object>>("1");
var deleteBulkRequest = new BulkRequest("my-test-index") { Operations = new BulkOperationsCollection { deleteOperation } };
var deleteResponse = await client.BulkAsync(deleteBulkRequest).ConfigureAwait(false);

The call to BulkAsync fails with the following exception:

# FailureReason: Unrecoverable/Unexpected BadRequest while attempting POST on https://localhost:9292/my-test-index/_bulk?pretty=true&error_trace=true
 - [1] BadRequest: Node: https://localhost:9292/ Exception: ArgumentException Took: 00:00:00.0059842
# Audit exception in step 1 BadRequest:
System.ArgumentException: Index name is null for the given type and no default index is set. Map an index name using ConnectionSettings.DefaultMappingFor<TDocument>() or set a default index using ConnectionSettings.DefaultIndex().
   at Elastic.Clients.Elasticsearch.IndexNameResolver.ValidateIndexName(String indexName) in /_/src/Elastic.Clients.Elasticsearch/Core/Infer/IndexName/IndexNameResolver.cs:line 49
   at Elastic.Clients.Elasticsearch.IndexNameResolver.Resolve(Type type) in /_/src/Elastic.Clients.Elasticsearch/Core/Infer/IndexName/IndexNameResolver.cs:line 39
   at Elastic.Clients.Elasticsearch.IndexNameResolver.Resolve(IndexName i) in /_/src/Elastic.Clients.Elasticsearch/Core/Infer/IndexName/IndexNameResolver.cs:line 24
   at Elastic.Clients.Elasticsearch.IndexNameConverter.Write(Utf8JsonWriter writer, IndexName value, JsonSerializerOptions options) in /_/src/Elastic.Clients.Elasticsearch/Core/Infer/IndexName/IndexNameConverter.cs:line 50
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
   at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
   at System.Text.Json.JsonSerializer.WriteUsingSerializer[TValue](Utf8JsonWriter writer, TValue& value, JsonTypeInfo jsonTypeInfo)
   at System.Text.Json.JsonSerializer.Serialize[TValue](Utf8JsonWriter writer, TValue value, JsonSerializerOptions options)
   at Elastic.Clients.Elasticsearch.Core.Bulk.BulkDeleteOperation.SerializeInternal(IElasticsearchClientSettings settings, Utf8JsonWriter writer) in /_/src/Elastic.Clients.Elasticsearch/Types/Core/Bulk/BulkDeleteOperation.cs:line 47
   at Elastic.Clients.Elasticsearch.Core.Bulk.BulkDeleteOperation.SerializeAsync(Stream stream, IElasticsearchClientSettings settings) in /_/src/Elastic.Clients.Elasticsearch/Types/Core/Bulk/BulkDeleteOperation.cs:line 32
   at Elastic.Clients.Elasticsearch.Core.Bulk.BulkDeleteOperation.SerializeAsync(Stream stream, IElasticsearchClientSettings settings) in /_/src/Elastic.Clients.Elasticsearch/Types/Core/Bulk/BulkDeleteOperation.cs:line 33
   at Elastic.Clients.Elasticsearch.BulkRequest.SerializeAsync(Stream stream, IElasticsearchClientSettings settings, SerializationFormatting formatting) in /_/src/Elastic.Clients.Elasticsearch/Api/BulkRequest.cs:line 66
   at Elastic.Transport.PostData.SerializableData`1.WriteAsync(Stream writableStream, ITransportConfiguration settings, CancellationToken cancellationToken)
   at Elastic.Transport.HttpTransportClient.SetContentAsync(HttpRequestMessage message, RequestData requestData, CancellationToken cancellationToken)
   at Elastic.Transport.HttpTransportClient.RequestCoreAsync[TResponse](Boolean isAsync, RequestData requestData, CancellationToken cancellationToken)
   at Elastic.Transport.DefaultRequestPipeline`1.CallProductEndpointCoreAsync[TResponse](Boolean isAsync, RequestData requestData, CancellationToken cancellationToken)
   at Elastic.Transport.DefaultHttpTransport`1.RequestCoreAsync[TResponse](Boolean isAsync, HttpMethod method, String path, PostData data, RequestParameters requestParameters, OpenTelemetryData openTelemetryData, CancellationToken cancellationToken)

As soon as the code is changed the following way (the index name IS NOT set for BulkRequest, but instead IS set for each BulkDeleteOperation):

var deleteOperation = new BulkDeleteOperation<IReadOnlyDictionary<string, object>>("1") { Index = "my-test-index" };
var deleteBulkRequest = new BulkRequest() { Operations = new BulkOperationsCollection { deleteOperation } };
var deleteResponse = await client.BulkAsync(deleteBulkRequest).ConfigureAwait(false);

It starts working just fine. So, the workaround is to mandatory specify the index for each bulk delete operation. This is not reproducible for bulk index operation, but IS reproducible if the bulk request contains AT LEAST ONE bulk delete operation. Specifying the index name on both levels doesn't help either.

Notes: I should say that the suggestion in the error message about using default index name in the settings is not relevant - in my app each BulkRequest might target a different index.

yansklyarenko avatar Nov 22 '23 09:11 yansklyarenko