{"record":{"id":"72b209125a65cf56","repo":"apache/druid","slug":"failed-to-load-initial-batch-of-results","errorCode":null,"errorMessage":"Failed to load initial batch of results","messagePattern":"Failed to load initial batch of results","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"processing/src/main/java/org/apache/druid/java/util/common/guava/ParallelMergeCombiningSequence.java","lineNumber":977,"sourceCode":"    private final int batchSize;\n    private volatile Yielder<ResultBatch<E>> batchYielder;\n\n    SequenceBatcher(Sequence<E> sequence, int batchSize)\n    {\n      this.sequence = sequence;\n      this.batchSize = batchSize;\n    }\n\n    Yielder<ResultBatch<E>> getBatchYielder()\n    {\n      try {\n        batchYielder = null;\n        ForkJoinPool.managedBlock(this);\n        return batchYielder;\n      }\n      catch (InterruptedException e) {\n        batchYielder = Yielders.done(null, null);\n        throw new RuntimeException(\"Failed to load initial batch of results\", e);\n      }\n    }\n\n    @Override\n    public boolean block()\n    {\n      batchYielder = ResultBatch.fromSequence(sequence, batchSize);\n      return true;\n    }\n\n    @Override\n    public boolean isReleasable()\n    {\n      return batchYielder != null;\n    }\n  }\n\n  /**","sourceCodeStart":959,"sourceCodeEnd":995,"githubUrl":"https://github.com/apache/druid/blob/9b90983fd291f26935af934383ce360473179e4d/processing/src/main/java/org/apache/druid/java/util/common/guava/ParallelMergeCombiningSequence.java#L959-L995","documentation":"In ParallelMergeCombiningSequence's yielder initialization, ForkJoinPool.managedBlock() waits for the first ResultBatch from a merge-combine worker. An InterruptedException while waiting is wrapped in a RuntimeException('Failed to load initial batch of results'), after marking the batchYielder done so resources are released.","triggerScenarios":"Thread interruption while the combining thread blocks waiting for the first batch of results from the parallel merge workers (e.g. during ParallelMergeCombiningSequence.toYielder).","commonSituations":"Query cancellation via QueryScheduler/timeout, broker cancellation endpoint, or server shutdown during the initial phase of a parallel merge combining sequence.","solutions":["Check the InterruptedException cause to identify the canceller (timeout vs explicit cancel)","Re-issue the query if it was cancelled transiently; otherwise fix the timeout/cancellation configuration","Ensure worker queues are healthy — slow producers make the initial batch wait long and vulnerable to cancellation"],"exampleFix":"// before\nYielder<...> y = seq.toYielder(init, acc); // interrupted\n// after\ntry {\n  Yielder<...> y = seq.toYielder(init, acc);\n} catch (RuntimeException e) {\n  if (e.getMessage().contains(\"Failed to load initial batch\") && e.getCause() instanceof InterruptedException) {\n    // handle cancellation explicitly\n  }\n  throw e;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { yielder = seq.toYielder(init, acc); } catch (RuntimeException e) {\n  if (\"Failed to load initial batch of results\".equals(e.getMessage()) && e.getCause() instanceof InterruptedException) { Thread.currentThread().interrupt(); }\n  else throw e;\n}","preventionTips":["Set sane query timeouts so merges finish before cancellation","Ensure parallel merge workers are not starved (adequate merge buffers/threads)","Restore the interrupt flag when catching to preserve cancellation semantics"],"tags":["parallelism","interruption","yielder","druid"],"backgroundTag":"request-timeout","analyzedSha":"9b90983fd291f26935af934383ce360473179e4d","analyzedAt":"2026-09-07T13:32:30.957Z","contentChangedAt":"2026-09-07T13:32:30.957Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}