LMAX-Exchange/disruptor · error · NullPointerException
batchRewindStrategy cannot be null when building a BatchEven
Error message
batchRewindStrategy cannot be null when building a BatchEventProcessor
What it means
Thrown by BatchEventProcessorBuilder.build(...) when batchRewindStrategy is null while constructing a processor for a RewindableEventHandler. The rewind path needs a strategy (e.g. SagaBatchRewindStrategy) to decide how many retries to attempt before giving up, so a null strategy cannot be defaulted silently.
Source
Thrown at src/main/java/com/lmax/disruptor/BatchEventProcessorBuilder.java:80
* Construct a {@link EventProcessor} that will automatically track the progress by updating its sequence when
* the {@link EventHandler#onEvent(Object, long, boolean)} method returns.
*
* @param dataProvider to which events are published.
* @param sequenceBarrier on which it is waiting.
* @param rewindableEventHandler is the delegate to which events are dispatched.
* @param batchRewindStrategy a {@link BatchRewindStrategy} for customizing how to handle a {@link RewindableException}.
* @param <T> event implementation storing the data for sharing during exchange or parallel coordination of an event.
* @return the BatchEventProcessor
*/
public <T> BatchEventProcessor<T> build(
final DataProvider<T> dataProvider,
final SequenceBarrier sequenceBarrier,
final RewindableEventHandler<? super T> rewindableEventHandler,
final BatchRewindStrategy batchRewindStrategy)
{
if (null == batchRewindStrategy)
{
throw new NullPointerException("batchRewindStrategy cannot be null when building a BatchEventProcessor");
}
return new BatchEventProcessor<>(
dataProvider, sequenceBarrier, rewindableEventHandler, maxBatchSize, batchRewindStrategy
);
}
}
View on GitHub (pinned to c871ca4982)
Solutions
- Pass a concrete BatchRewindStrategy, e.g. new SagaBatchRewindStrategy(3), to build(...).
- If you do not want retries, still pass a strategy that immediately rethrows (implement BatchRewindStrategy to throw the exception).
- If using DI, ensure the strategy bean is defined and injected in all profiles including tests.
Example fix
// before BatchEventProcessor<Event> p = builder.build(ringBuffer, barrier, handler, null); // after BatchEventProcessor<Event> p = builder.build(ringBuffer, barrier, handler, new SagaBatchRewindStrategy(3));
Defensive patterns
Strategy: validation
Validate before calling
BatchRewindStrategy strategy = (strategyBean != null)
? strategyBean
: new SagaBatchRewindStrategy(3); Type guard
static boolean isUsableStrategy(BatchRewindStrategy s) { return s != null; } Prevention
- Never pass a literal null to builder.build(...); always construct a strategy inline.
- Enable nullness annotations (@NonNull) on your own builder wrappers around Disruptor.
When it happens
Trigger: Calling the four-argument build(dataProvider, sequenceBarrier, rewindableEventHandler, null), or passing a strategy field that was never initialised.
Common situations: Builder wiring copied from an example where the strategy was created inline; dependency injection leaving the strategy bean null in a test profile; upgrading Disruptor versions where build() gained the batchRewindStrategy parameter and call sites were not all updated.
Related errors
- bufferSize must not be less than 1
- bufferSize must be a power of 2
- maxBatchSize must be greater than 0
- Rewindable Exception thrown from a non-rewindable event hand
- n must be > 0 and < bufferSize
AI-assisted analysis of LMAX-Exchange/disruptor@c871ca4982 (2026-08-14).
Data as JSON: /api/errors/1ba9d64eb10e1892.
Report an issue: GitHub.