aeron-io/aeron · error · ArchiveException
client is closed
Error message
client is closed
What it means
AeronArchive tracks its connection lifecycle with a State enum. This guard is in the code path that verifies the client is CONNECTED before performing work; if the state is CLOSED, further use is impossible, so the library throws this ArchiveException instead of proceeding on a dead connection.
Solutions
- Check AeronArchive.state() / isClosed() before use, or hold a single reference and stop using it after close().
- Create a new AeronArchive instance (AeronArchive.connect(ctx)) to replace the closed one.
- Reorder shutdown so all archive work completes before close(), and make worker threads observe a shutdown flag.
- Catch ArchiveException in the worker loop and treat it as a shutdown signal.
Example fix
// before
archive.startRecording(channel, streamId, SourceLocation.LOCAL); // may be closed
// after
if (archive.isClosed())
{
archive = AeronArchive.connect(archiveCtx);
}
archive.startRecording(channel, streamId, SourceLocation.LOCAL); Defensive patterns
Strategy: validation
Validate before calling
if (archive == null || archive.isClosed()) { archive = AeronArchive.connect(archiveCtx.clone()); } Type guard
boolean usable(AeronArchive a) { return a != null && !a.isClosed(); } Prevention
- Check isClosed() before each archive operation in long-lived workers.
- Centralize archive access in one owner component that recreates the client on demand.
- Order shutdown: finish archive work, then close the client, then close Aeron.
- Never cache AeronArchive across application restarts or error-handler closes.
When it happens
Trigger: Calling any AeronArchive method (e.g. startRecording, stopRecording, pollForNextResponse) after close() was called on the archive client, or a timeout/error path closed the connection internally.
Common situations: Application shutdown ordering where the archive client is closed while worker threads still use it; catching a connect timeout elsewhere and continuing; reusing an archive client across requests after an error handler closed it.
Understand the failure class
Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.
Related errors
- Publication is closed
- counter is closed
- Aeron client instance must set…
- Aeron client must use a RethrowingErrorHandler
- segment file length not a power of 2
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/bd3097cc09f59fab.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java:2594
private void dispatchRecordingSignal(final ControlResponsePoller poller)
{
context.recordingSignalConsumer().onSignal(
poller.controlSessionId(),
poller.correlationId(),
poller.recordingId(),
poller.subscriptionId(),
poller.position(),
poller.recordingSignal());
}
private void ensureConnected()
{
final State currentState = state;
if (State.CONNECTED != currentState)
{
if (State.CLOSED == currentState)
{
throw new ArchiveException("client is closed");
}
else
{
close();
}
}
}
private void ensureNotReentrant()
{
if (isInCallback)
{
throw new AeronException("reentrant calls not permitted during callbacks");
}
}
private void state(final State newState)
{View on GitHub (pinned to 6d60124e15)