Hacktoberfest 2026: le issue che i maintainer hanno segnato per ottobre, aperte e adatte ai principianti. Sfoglia le issue Hacktoberfest

Delete By Query deserialization will not account for search failures

Aperta
#1,349 1 commento 0 reazioni 1 assegnatario Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

@l-trotta ci sta già lavorando.

Dal 2/10/2026.

Valutazione

Questa issue non è ancora stata valutata.

Descrizione

Java API client version

8.14.3

Java version

21

Elasticsearch Version

8.19.11

Problem description

Delete by query's response field has a section for failures that is strictly typed as BulkIndexByScrollFailure. However, in the DeleteByQueryResponse that upstream Elasticsearch can return, the failures list is a union of search failures and indexing failures, and the search failures has a different serialization format than the indexing failures (ES9, ES8). Specifically, search failures put the error under reason, and the bulk failures put the error under cause. The result is that if a search failure is serialized by the server, the client fails to deserialize into a DeleteByQueryResponse correctly unless the default deserializer is overridden accordingly.

Reproducing this is challenging in an isolated case because it requires actually reproducing a search failure that serializes this way. The following is contrived, but can sometimes show the issue if given enough attempts - it tries to specifically close the index under deletion in the middle of one of the scroll iterations of a delete by query job.

        ElasticsearchClient client = <create client here>;
        String prefix = "dbq-search-failure-" + UUID.randomUUID();
        String available = prefix + "-available";
        String disappearing = prefix + "-disappearing";
        ExecutorService executor = Executors.newSingleThreadExecutor();
        try {
            for (String index : List.of(available, disappearing)) {
                client.indices().create(request -> request.index(index)
                        .settings(settings -> settings.numberOfShards("1").numberOfReplicas("0")));
            }
            // Sorting keeps the first batches on the available index, avoiding a bulk write failure when the
            // other index closes. Its scroll context still participates, so a later scroll has a search failure.
            for (int position = 0; position < 5; position++) {
                String id = Integer.toString(position);
                Map<String, Integer> document = Map.of("position", position);
                client.index(request -> request.index(available).id(id).document(document));
            }
            client.index(request -> request.index(disappearing).id("last").document(Map.of("position", 100)));
            client.indices().refresh(request -> request.index(available, disappearing));

            Future<DeleteByQueryResponse> deletion = executor.submit(() -> client.deleteByQuery(request -> request
                    .index(available, disappearing)
                    .query(query -> query.matchAll(all -> all))
                    .sort("position:asc")
                    .scrollSize(1L)
                    .scroll(scroll -> scroll.time("1m"))
                    .requestsPerSecond(0.1f)));

            // The first deletion proves the initial search succeeded and both scroll contexts were created.
            long deadline = System.nanoTime() + TimeUnit.SECONDS.toNanos(15);
            while (client.exists(request -> request.index(available).id("0")).value()) {
                if (System.nanoTime() >= deadline) {
                    throw new AssertionError("Delete-by-query did not finish its first batch");
                }
                Thread.sleep(50);
            }
            client.indices().close(request -> request.index(disappearing));

            try {
                // Expected: a result with failures[0].reason.type == search_context_missing_exception.
                // Actual: the generated client models every failure as BulkIndexByScrollFailure.
                return deletion.get(45, TimeUnit.SECONDS);
            } catch (ExecutionException failure) {
                if (failure.getCause() instanceof Exception cause) {
                    throw cause;
                }
                throw failure;
            }
        } finally {
            executor.shutdownNow();
            client.indices().delete(request -> request.index(available, disappearing).ignoreUnavailable(true));
        }
Lingua principale
Java
Stelle
524
Fork
299
Merge medio
16m
PR unite (30g)
13

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di elastic/elasticsearch-java

Tutte le issue di elastic/elasticsearch-java

Issue simili

Altre issue su Java

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.