aeron-io/aeron · error · ClusterException
local archive control must be IPC
Error message
local archive control must be IPC
What it means
ClusteredServiceContainer requires that when a clustered service runs in the same JVM as the archive (local archive), the AeronArchive control request and response channels must use the IPC protocol (aeron:ipc) instead of a network transport. This avoids inter-JVM hops for archive control within the cluster node. If either channel is not IPC, a ClusterException is thrown during Context configuration.
Solutions
- Set the archive control request channel to 'aeron:ipc' (e.g. archiveContext.controlRequestChannel(CommonContext.IPC_CHANNEL)).
- Set the archive control response channel to 'aeron:ipc' as well.
- If the archive is genuinely remote, embed a local archive for the cluster node instead of reusing a remote one.
- Check cluster directory / system properties (aeron.archive.control.* overrides) for values forcing network channels.
Example fix
// before
archiveContext.controlRequestChannel("aeron:udp?endpoint=localhost:8010");
// after
archiveContext.controlRequestChannel(CommonContext.IPC_CHANNEL);
archiveContext.controlResponseChannel(CommonContext.IPC_CHANNEL); Defensive patterns
Strategy: validation
Validate before calling
if (!archiveContext.controlRequestChannel().startsWith("aeron:ipc")) {
archiveContext.controlRequestChannel("aeron:ipc");
} Prevention
- Always use CommonContext.IPC_CHANNEL constant, never string literals, for local archive channels.
- Do not copy archive channel settings from standalone archive clients into cluster service containers.
- Unit-test container Context configuration in CI to catch channel misconfig before runtime.
When it happens
Trigger: Configuring ClusteredServiceContainer.Context with an archiveContext whose controlRequestChannel() or controlResponseChannel() does not start with 'aeron:ipc' while the container expects a local (embedded) archive.
Common situations: Pointing the cluster's archive context at a remote archive via UDP channels; copying archive channel config from a standalone (non-cluster) example; setting AERON_ARCHIVE_CONTROL_CHANNEL env/config to a network channel instead of aeron:ipc.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- Aeron client instance must set…
- Aeron client must use a RethrowingErrorHandler
- segment file length not a power of 2
- segment file length not in valid range
- Unable to derive…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/da6f62a84a830e2e.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/service/ClusteredServiceContainer.java:1023
clusterId,
serviceId
),
snapshotDurationThresholdNs);
}
if (null == archiveContext)
{
archiveContext = new AeronArchive.Context()
.controlRequestChannel(AeronArchive.Configuration.localControlChannel())
.controlResponseChannel(AeronArchive.Configuration.localControlChannel())
.controlRequestStreamId(AeronArchive.Configuration.localControlStreamId())
.controlResponseStreamId(
clusterId * 100 + 100 + AeronArchive.Configuration.controlResponseStreamId() + (serviceId + 1));
}
if (!archiveContext.controlRequestChannel().startsWith(CommonContext.IPC_CHANNEL))
{
throw new ClusterException("local archive control must be IPC");
}
if (!archiveContext.controlResponseChannel().startsWith(CommonContext.IPC_CHANNEL))
{
throw new ClusterException("local archive control must be IPC");
}
archiveContext
.aeron(aeron)
.ownsAeronClient(false)
.lock(NoOpLock.INSTANCE)
.errorHandler(null) // propagate errors directly
.controlRequestChannel(addAliasIfAbsent(
archiveContext.controlRequestChannel(),
"sc-" + serviceId + "-archive-ctrl-req-cluster-" + clusterId))
.controlResponseChannel(addAliasIfAbsent(
archiveContext.controlResponseChannel(),
"sc-" + serviceId + "-archive-ctrl-resp-cluster-" + clusterId))View on GitHub (pinned to 6d60124e15)