aeron-io/aeron · error · ConfigurationException

replayStreamId must be set

Error message

replayStreamId must be set

What it means

conclude() checks that replayStreamId was set (i.e. not Aeron.NULL_VALUE). The replay stream id identifies the stream on the replayChannel used to deliver recorded data from the archive. Leaving it at the NULL_VALUE sentinel means the replay destination is incompletely specified, so a ConfigurationException is thrown.

Solutions

  1. Call replayStreamId(<positive int>) on the Context before conclude().
  2. If the same stream id is used for both paths, set it explicitly on both liveStreamId and replayStreamId.
  3. Ensure the config source supplying the replay stream id is present and parsed.

Example fix

// before
ctx.replayChannel("aeron:udp?endpoint=localhost:10001");
ctx.conclude(); // throws: replayStreamId must be set (still NULL_VALUE)

// after
ctx.replayChannel("aeron:udp?endpoint=localhost:10001");
ctx.replayStreamId(7);
ctx.conclude();
Defensive patterns

Strategy: validation

Validate before calling

if (Aeron.NULL_VALUE == ctx.replayStreamId()) {
    throw new IllegalArgumentException("replayStreamId must be set before conclude()");
}

Try / catch

try {
    ctx.conclude();
} catch (ConfigurationException e) {
    // fall back to liveStreamId if streams are shared
}

Prevention

When it happens

Trigger: conclude() called with replayStreamId never assigned (defaults to Aeron.NULL_VALUE), or explicitly set to Aeron.NULL_VALUE (-1).

Common situations: Setting liveStreamId and assuming it applies to replay too; forgetting the streamId setter while changing channels; programmatic construction where streamIds come from separate config keys and the replay one is missing.

Understand the failure class

Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/53036fc820a9a305. Report an issue: GitHub.

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/client/PersistentSubscription.java:1702

            if (Aeron.NULL_VALUE == liveStreamId)
            {
                throw new ConfigurationException("liveStreamId must be set");
            }

            if (Strings.isEmpty(liveChannel))
            {
                throw new ConfigurationException("liveChannel must be set");
            }

            if (Strings.isEmpty(replayChannel))
            {
                throw new ConfigurationException("replayChannel must be set");
            }

            if (Aeron.NULL_VALUE == replayStreamId)
            {
                throw new ConfigurationException("replayStreamId must be set");
            }

            if (null == aeronArchiveContext)
            {
                throw new ConfigurationException("aeronArchiveContext must be set");
            }

            if (null == listener)
            {
                listener = new NoOpPersistentSubscriptionListener();
            }

            if (0 > recordingId)
            {
                throw new ConfigurationException("invalid recordingId " + recordingId);
            }

            if (FROM_LIVE > startPosition)

View on GitHub (pinned to 6d60124e15)