aeron-io/aeron · error · ArchiveException
publication already added for channel=" + channel + "…
Error message
publication already added for channel=" + channel + " streamId=" + streamId
What it means
addRecordedPublication adds a publication for the given channel/streamId and then asks the archive to record it. Aeron publications have an 'original' flag: only the first publication for a channel+streamId pair in this client is original. If the publication is not original, the same channel/streamId was already added, and the library throws ArchiveException to prevent double-adding a recorded publication.
Solutions
- Call addRecordedPublication only once per channel/streamId per Aeron client; track existing publications before adding
- Close the previously created publication before re-adding, or use a distinct session id in the channel URI
- Use tryStopRecording/stopRecording and close publications, then retry the add if a duplicate is suspected
Example fix
// before
archive.addRecordedPublication(channel, streamId);
archive.addRecordedPublication(channel, streamId); // throws: publication already added
// after
Publication pub = aeron.addPublication(channel, streamId);
if (!existingRecordings.contains(channel + streamId)) {
archive.addRecordedPublication(channel, streamId);
} Defensive patterns
Strategy: validation
Validate before calling
// track channels+streamIds already being recorded by this Aeron client
if (recordedChannels.contains(channel + "|" + streamId)) {
return; // already added
} Try / catch
try {
archive.addRecordedPublication(channel, streamId);
} catch (ArchiveException ex) {
if (ex.getMessage().startsWith("publication already added")) {
// skip: recording already in place
}
} Prevention
- Keep one owner per recorded channel/streamId per Aeron client
- On retry after failure, close the previously created publication first
- Use unique session ids in channel URIs when multiple recordings of the same stream are needed
When it happens
Trigger: Calling AeronArchive.addRecordedPublication(channel, streamId) with a channel+streamId for which this Aeron client already created a publication (e.g. calling the method twice, or reusing an existing publication's channel/streamId).
Common situations: Application retry logic re-invoking addRecordedPublication after an error without cleanup; two components sharing one Aeron client each attempting to record the same channel/streamId; re-subscribing/re-adding after reconnect without closing prior publications.
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
- catalogFileSyncLevel
- invalid fileIoMaxLength=
- Archive.Context.controlChannel must be set
- Archive.Context.controlChannel must be UDP media: uri=
- local control channel must be IPC media: uri=
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/e076686bbf60e121.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-archive/src/main/java/io/aeron/archive/client/AeronArchive.java:621
* This is a sessionId specific recording.
*
* @param channel for the publication.
* @param streamId for the publication.
* @return the {@link Publication} ready for use.
*/
public Publication addRecordedPublication(final String channel, final int streamId)
{
Publication publication = null;
lock.lock();
try
{
ensureConnected();
ensureNotReentrant();
publication = aeron.addPublication(channel, streamId);
if (!publication.isOriginal())
{
throw new ArchiveException(
"publication already added for channel=" + channel + " streamId=" + streamId);
}
startRecording(ChannelUri.addSessionId(channel, publication.sessionId()), streamId, SourceLocation.LOCAL);
}
catch (final RuntimeException ex)
{
CloseHelper.quietClose(publication);
throw ex;
}
finally
{
lock.unlock();
}
return publication;
}
View on GitHub (pinned to 6d60124e15)