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

  1. Pass a concrete BatchRewindStrategy, e.g. new SagaBatchRewindStrategy(3), to build(...).
  2. If you do not want retries, still pass a strategy that immediately rethrows (implement BatchRewindStrategy to throw the exception).
  3. 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

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


AI-assisted analysis of LMAX-Exchange/disruptor@c871ca4982 (2026-08-14). Data as JSON: /api/errors/1ba9d64eb10e1892. Report an issue: GitHub.