aeron-io/aeron · error · ConfigurationException

recordingId must be set

Error message

recordingId must be set

What it means

PersistentSubscription.Builder.conclude() validates required fields and throws ConfigurationException("recordingId must be set") when recordingId is still Aeron.NULL_VALUE. A persistent subscription cannot be created without knowing which recording it consumes.

Solutions

  1. Call builder.recordingId(id) with a valid (non-NULL_VALUE) recording id before conclude()
  2. Obtain the recording id from AeronArchive.listRecording/listRecordingsForUri before building the subscription
  3. Validate configuration/arguments that supply the recording id early with a clear failure
  4. Start the recording first, capture the returned recordingId, then construct the persistent subscription

Example fix

// before
PersistentSubscription.Builder b = new PersistentSubscription.Builder();
b.conclude(); // recordingId never set

// after
long recordingId = aeronArchive.startRecording(channel, streamId, LOCAL);
b.recordingId(recordingId).liveChannel(liveChannel).liveStreamId(streamId);
b.conclude();
Defensive patterns

Strategy: validation

Validate before calling

if (recordingId == Aeron.NULL_VALUE) {
    throw new IllegalArgumentException("recordingId must be resolved before building PersistentSubscription");
}

Type guard

boolean hasRecordingId(PersistentSubscription.Builder b) { return recordingId != Aeron.NULL_VALUE; }

Try / catch

try {
    builder.conclude();
} catch (ConfigurationException e) {
    if (e.getMessage().equals("recordingId must be set")) {
        throw new IllegalStateException("resolve recording id via AeronArchive before subscribing", e);
    }
}

Prevention

When it happens

Trigger: Calling conclude() on a PersistentSubscription.Builder whose recordingId() was never called (or was set to Aeron.NULL_VALUE, e.g. from an unset/failed replay-destination lookup).

Common situations: Configuration code that conditionally sets recordingId but the condition failed silently; parsing a recording id from config/args returned null/default; initializing the subscription before the recording was actually started and its id obtained.

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


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/705b90522b4e764d. Report an issue: GitHub.

Appendix: source

Thrown at aeron-archive/src/main/java/io/aeron/archive/client/PersistentSubscription.java:1682

            {
                throw new RuntimeException(ex);
            }
        }

        /**
         * Conclude configuration by setting up defaults when specifics are not provided.
         */
        @SuppressWarnings("MethodLength")
        public void conclude()
        {
            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)

View on GitHub (pinned to 6d60124e15)