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
- Call liveChannel("aeron:udp?endpoint=...") (or ipc URI) on the PersistentSubscription.Context before conclude().
- If building via a helper/builder, pass the live channel in the constructor or setter it exposes.
- 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
- Always set liveChannel, liveStreamId, replayChannel and replayStreamId together in one builder method.
- Validate all channel URIs are non-empty right after loading config, before constructing the subscription.
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
- replayChannel must be set
- catalogFileSyncLevel
- invalid fileIoMaxLength=
- Archive.Context.controlChannel must be set
- Archive.Context.controlChannel must be UDP media: uri=
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)