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 tickingView on GitHub (pinned to 5ce3bc58c3)
Solutions
- Ensure HystrixRequestContext.shutdown()/Hystrix.reset() happens only after all in-flight collapsers complete (drain futures first in @After/test teardown)
- Avoid submitting new collapsed requests on a thread whose context has been shut down; re-initialize the context
- Retry the collapser invocation on a fresh context if the race window is inherent
- 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
- Never submit collapsed work after HystrixRequestContext.shutdown()/Hystrix.reset()
- Drain in-flight collapser futures before resetting Hystrix in tests
- Keep collapser submission on the thread that owns the request context
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
- HystrixCollapser failed while executing.
- Not an event that can be converted to HystrixEventType.Colla
- Interrupted while waiting for thread-pools to terminate. Poo
- Response has already terminated so response can not be set :
- Response has already terminated so exception can not be set
AI-assisted analysis of Netflix/Hystrix@5ce3bc58c3 (2026-08-14).
Data as JSON: /api/errors/b8f62d00bf9339e2.
Report an issue: GitHub.