aeron-io/aeron · error · ConfigurationException

invalid startPosition

Error message

invalid startPosition 

What it means

conclude() validates startPosition against the lowest legal sentinel: FROM_LIVE (-1) is the smallest allowed value, meaning 'join the live stream now'. Any smaller value (typically Aeron.NULL_VALUE = -2 when never set, or a corrupt negative) is invalid, so a ConfigurationException with the offending value is thrown.

Solutions

  1. Set a valid startPosition: a non-negative byte position within the recording, or PersistentSubscription.FROM_LIVE to follow the live stream.
  2. If you want to replay from the recording start, use position 0 (or the recording's startPosition from the descriptor).
  3. Fix the calculation producing a negative position (e.g. clamp or validate before passing).

Example fix

// before
ctx.startPosition(Aeron.NULL_VALUE); // -2 < FROM_LIVE(-1)
ctx.conclude(); // throws: invalid startPosition -2

// after
ctx.startPosition(0); // replay from recording start
// or ctx.startPosition(PersistentSubscription.FROM_LIVE); // follow live
Defensive patterns

Strategy: validation

Validate before calling

if (startPosition < PersistentSubscription.FROM_LIVE) {
    throw new IllegalArgumentException("startPosition must be >= FROM_LIVE(-1), got " + startPosition);
}

Try / catch

try {
    ctx.conclude();
} catch (ConfigurationException e) {
    // clamp to FROM_LIVE or 0 and retry
}

Prevention

When it happens

Trigger: conclude() called with startPosition < FROM_LIVE, e.g. startPosition left at Aeron.NULL_VALUE (-2), or an application passing a negative position it computed itself.

Common situations: Forgetting to call startPosition(...) and assuming NULL_VALUE means 'from beginning'; confusing FROM_LIVE (-1) with NULL_VALUE (-2); passing a recordingPosition read before the recording began as a negative number.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

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

            if (null == aeronArchiveContext)
            {
                throw new ConfigurationException("aeronArchiveContext must be set");
            }

            if (null == listener)
            {
                listener = new NoOpPersistentSubscriptionListener();
            }

            if (0 > recordingId)
            {
                throw new ConfigurationException("invalid recordingId " + recordingId);
            }

            if (FROM_LIVE > startPosition)
            {
                throw new ConfigurationException("invalid startPosition " + startPosition);
            }

            final ChannelUri replayChannelUri = ChannelUri.parse(replayChannel);

            if (replayChannelUri.hasControlModeResponse())
            {
                final String controlRequestChannel = aeronArchiveContext.controlRequestChannel();
                if (null != controlRequestChannel &&
                    !replayChannelUri.isIpc() == ChannelUri.parse(controlRequestChannel).isIpc()
                )
                {
                    throw new ConfigurationException(
                        "Channel media type mismatch. " +
                            "When using `control-mode=response`, the `replayChannel` media type must match the media" +
                            " type for the archive control channel."
                    );
                }
            }

View on GitHub (pinned to 6d60124e15)