aeron-io/aeron · error · IllegalArgumentException
invalid position= < 0
Error message
invalid position=${position} < 0 What it means
ChannelUriStringBuilder.initialPosition(position, initialTermId, termLength) computes the term offset from the given absolute position and rejects negative positions outright. Positions in Aeron are non-negative 64-bit stream offsets; a negative value indicates corrupted arithmetic or a wrongly decoded position. (A second check in the same method also requires frame alignment of 32 bytes.)
Solutions
- Fix the source of the position so it is never negative before calling initialPosition
- Validate the position and reject/repair negative values: if (position < 0) throw or reset to 0
- Also ensure the position is a multiple of FRAME_ALIGNMENT (32) or the next check will throw
- Use values from Aeron's own position APIs (publication.position(), image.position()) which are guaranteed non-negative
Example fix
// before long pos = recordedPosition - basePosition; // can underflow builder.initialPosition(pos, termId, termLength); // after long pos = Math.max(0, recordedPosition - basePosition); pos &= ~(32 - 1); // align to FRAME_ALIGNMENT builder.initialPosition(pos, termId, termLength);
Defensive patterns
Strategy: validation
Validate before calling
int FRAME_ALIGNMENT = 32;
if (position < 0) throw new IllegalArgumentException("position must be >= 0");
if ((position & (FRAME_ALIGNMENT - 1)) != 0) throw new IllegalArgumentException("position must be 32-byte aligned"); Try / catch
try { builder.initialPosition(pos, termId, termLength); } catch (IllegalArgumentException e) { /* clamp/recompute pos */ } Prevention
- Persist positions from Aeron APIs (publication.position()) which are non-negative and aligned
- Guard against underflow when computing relative positions
- Align positions to 32 bytes before calling initialPosition
When it happens
Trigger: Calling initialPosition(-1, termId, termLength), or passing a position computed by subtraction that underflowed, or one decoded from a packed long that lost its sign handling.
Common situations: Restoring a publication/replay position from persistent state where the stored value was corrupted; subtracting a larger position from a smaller one; casting unsigned 64-bit values above Long.MAX_VALUE to a negative long.
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- term length more than max length of
- term offset not in range 0-1g
- 'initial-term-id' must be a valid integer
- 'term-id' must be a valid integer
- term offset not multiple of FRAME_ALIGNMENT
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/5109010fb1235332.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java:1629
*/
public Boolean spiesSimulateConnection()
{
return ssc;
}
/**
* Initialise a channel for restarting a publication at a given position.
*
* @param position at which the publication should be started.
* @param initialTermId what which the stream would start.
* @param termLength for the stream.
* @return this for a fluent API.
*/
public ChannelUriStringBuilder initialPosition(final long position, final int initialTermId, final int termLength)
{
if (position < 0)
{
throw new IllegalArgumentException("invalid position=" + position + " < 0");
}
if (0 != (position & (FRAME_ALIGNMENT - 1)))
{
throw new IllegalArgumentException(
"invalid position=" + position + " does not have frame alignment=" + FRAME_ALIGNMENT);
}
final int bitsToShift = LogBufferDescriptor.positionBitsToShift(termLength);
this.initialTermId = initialTermId;
this.termId = LogBufferDescriptor.computeTermIdFromPosition(position, bitsToShift, initialTermId);
this.termOffset = (int)(position & (termLength - 1));
this.termLength = termLength;
return this;
}
/**View on GitHub (pinned to 6d60124e15)