Netflix/Hystrix · error · IllegalStateException

Trying to start null batch which means it was shutdown alrea

Error message

Trying to start null batch which means it was shutdown already.

What it means

RequestCollapser.createNewBatchAndExecutePreviousIfNeeded() requires the previous batch reference to be non-null; null means shutdown() already swapped the batch reference to null via batch.getAndSet(null), so trying to start a new batch post-shutdown throws IllegalStateException('Trying to start null batch which means it was shutdown already.').

Source

Thrown at hystrix-core/src/main/java/com/netflix/hystrix/collapser/RequestCollapser.java:111

            final Observable<ResponseType> response;
            if (arg != null) {
                response = b.offer(arg);
            } else {
                response = b.offer( (RequestArgumentType) NULL_SENTINEL);
            }
            // it will always get an Observable unless we hit the max batch size
            if (response != null) {
                return response;
            } else {
                // this batch can't accept requests so create a new one and set it if another thread doesn't beat us
                createNewBatchAndExecutePreviousIfNeeded(b);
            }
        }
    }

    private void createNewBatchAndExecutePreviousIfNeeded(RequestBatch<BatchReturnType, ResponseType, RequestArgumentType> previousBatch) {
        if (previousBatch == null) {
            throw new IllegalStateException("Trying to start null batch which means it was shutdown already.");
        }
        if (batch.compareAndSet(previousBatch, new RequestBatch<BatchReturnType, ResponseType, RequestArgumentType>(properties, commandCollapser, properties.maxRequestsInBatch().get()))) {
            // this thread won so trigger the previous batch
            previousBatch.executeBatchIfNotAlreadyStarted();
        }
    }

    /**
     * Called from RequestVariable.shutdown() to unschedule the task.
     */
    public void shutdown() {
        RequestBatch<BatchReturnType, ResponseType, RequestArgumentType> currentBatch = batch.getAndSet(null);
        if (currentBatch != null) {
            currentBatch.shutdown();
        }

        if (timerListenerReference.get() != null) {
            // if the timer was started we'll clear it so it stops ticking

View on GitHub (pinned to 5ce3bc58c3)

Solutions

  1. Ensure HystrixRequestContext.shutdown()/Hystrix.reset() happens only after all in-flight collapsers complete (drain futures first in @After/test teardown)
  2. Avoid submitting new collapsed requests on a thread whose context has been shut down; re-initialize the context
  3. Retry the collapser invocation on a fresh context if the race window is inherent
  4. Upgrade Hystrix patch level if hitting a known collapser shutdown race

Example fix

// before
@After public void tearDown() { Hystrix.reset(); } // races in-flight collapsers
// after
@After public void tearDown() {
  pendingFutures.forEach(f -> f.get(2, TimeUnit.SECONDS)); // drain first
  Hystrix.reset();
}
Defensive patterns

Strategy: retry

Validate before calling

// verify context/collapser usability before submitting
if (!HystrixRequestContext.isCurrentThreadInitialized()) { HystrixRequestContext.initializeContext(); /* ... */ }

Type guard

null

Try / catch

catch (IllegalStateException e) { if (e.getMessage().contains("null batch")) { // shutdown race: re-initialize request context and retry once with a new collapser instance } }

Prevention

When it happens

Trigger: A request arrives via offer() after RequestCollapser.shutdown() ran — the read of the batch field yielded null and code falls into createNewBatchAndExecutePreviousIfNeeded(null); a race between collapser request submission (Scope.REQUEST teardown, Hystrix.reset(), or request-context shutdown) and an in-flight command.

Common situations: Hystrix.reset() in test @After racing with still-executing collapsed commands; application shutdown while collapsed requests are in flight; request-scoped collapsers used after the request context was torn down; typically seen as a rare race in tests rather than production.

Related errors


AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14). Data as JSON: /api/errors/b8f62d00bf9339e2. Report an issue: GitHub.