aeron-io/aeron · error · ConfigurationException

liveChannel must be set

Error message

liveChannel must be set

What it means

PersistentSubscription.Context.conclude() validates that a liveChannel URI was configured before the subscription can be created. The live channel is the Aeron channel on which the subscription originally listens for live data before switching to replay. A ConfigurationException is thrown when the channel is null or empty because a persistent subscription cannot be constructed without it.

Solutions

  1. Call liveChannel("aeron:udp?endpoint=...") (or ipc URI) on the PersistentSubscription.Context before conclude().
  2. If building via a helper/builder, pass the live channel in the constructor or setter it exposes.
  3. Ensure the value is non-null and non-empty (Strings.isEmpty is the check).

Example fix

// before
final PersistentSubscription.Context ctx = new PersistentSubscription.Context()
    .recordingId(recordingId)
    .replayChannel("aeron:udp?endpoint=localhost:10001")
    .replayStreamId(7);
ctx.conclude(); // throws: liveChannel must be set

// after
final PersistentSubscription.Context ctx = new PersistentSubscription.Context()
    .recordingId(recordingId)
    .liveChannel("aeron:udp?endpoint=localhost:10000")
    .liveStreamId(5)
    .replayChannel("aeron:udp?endpoint=localhost:10001")
    .replayStreamId(7);
ctx.conclude();
Defensive patterns

Strategy: validation

Validate before calling

if (Strings.isEmpty(ctx.liveChannel())) {
    throw new IllegalArgumentException("liveChannel must be set before conclude()");
}

Try / catch

try {
    ctx.conclude();
} catch (ConfigurationException e) {
    // log and re-check liveChannel configuration
}

Prevention

When it happens

Trigger: Calling PersistentSubscription.Context.conclude() (directly or via a constructor/build path) without ever calling context.liveChannel(String), or setting it to null/empty string. Also occurs when a builder for a persistent subscription omits the live channel.

Common situations: Constructing a PersistentSubscription programmatically with only recordingId/replay parameters set; copy-pasting a replay-only setup and forgetting the live side; migration from older archive client APIs where the live channel defaulted implicitly.

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/7edd7e1c2b5c83ed. Report an issue: GitHub.

Appendix: source

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

        {
            if ((boolean)IS_CONCLUDED_VH.getAndSet(this, true))
            {
                throw new ConcurrentConcludeException();
            }

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

            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)

View on GitHub (pinned to 6d60124e15)