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

  1. Call addRecordedPublication only once per channel/streamId per Aeron client; track existing publications before adding
  2. Close the previously created publication before re-adding, or use a distinct session id in the channel URI
  3. 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

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


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)