aeron-io/aeron · error · IllegalArgumentException
term offset not multiple of FRAME_ALIGNMENT
Error message
term offset not multiple of FRAME_ALIGNMENT: ${termOffset} What it means
ChannelUriStringBuilder.termOffset(Integer) requires the offset to be a multiple of FRAME_ALIGNMENT (32 bytes). Offsets must point at message frame boundaries inside the term buffer; an unaligned offset would corrupt frame parsing. This is thrown after the range check and before the value is stored.
Solutions
- Round the offset down to the frame alignment: offset & ~(FRAME_ALIGNMENT - 1) with FRAME_ALIGNMENT=32
- Use initialPosition(...) with an already-aligned position so the offset is derived correctly
- Verify that whatever produced the offset aligns positions to 32-byte frames
Example fix
// before builder.termOffset(100); // not multiple of 32 // after builder.termOffset(96); // 100 & ~31 == 96
Defensive patterns
Strategy: validation
Validate before calling
int FRAME_ALIGNMENT = 32; if (termOffset != null && (termOffset & (FRAME_ALIGNMENT - 1)) != 0) termOffset &= ~(FRAME_ALIGNMENT - 1);
Try / catch
try { builder.termOffset(offset); } catch (IllegalArgumentException e) { builder.termOffset(offset & ~31); } Prevention
- Always align offsets to 32-byte frame boundaries before use
- Derive offsets from Aeron positions rather than raw stream counters
- Document that FRAME_ALIGNMENT is fixed at 32 for standard channels
When it happens
Trigger: Calling termOffset() with any value not divisible by 32, e.g. termOffset(100), or URIs with 'term-offset=50'.
Common situations: Deriving offsets from raw stream positions without aligning to frame boundaries; manually tuning replay/resume points; constructing URIs from arbitrary recorded positions.
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
- invalid position
- MTU not a multiple of FRAME_ALIGNMENT: mtu=
- term length more than max length of
- 'initial-term-id' must be a valid integer
- 'term-id' must be a valid integer
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/5aa0e86436e22e16.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-client/src/main/java/io/aeron/ChannelUriStringBuilder.java:843
* Set the offset within a term at which a publication will start. This when combined with the term id can establish
* a starting position.
*
* @param termOffset within a term at which a publication will start.
* @return this for a fluent API.
* @see CommonContext#TERM_OFFSET_PARAM_NAME
*/
public ChannelUriStringBuilder termOffset(final Integer termOffset)
{
if (null != termOffset)
{
if ((termOffset < 0 || termOffset > TERM_MAX_LENGTH))
{
throw new IllegalArgumentException("term offset not in range 0-1g: " + termOffset);
}
if (0 != (termOffset & (FRAME_ALIGNMENT - 1)))
{
throw new IllegalArgumentException("term offset not multiple of FRAME_ALIGNMENT: " + termOffset);
}
}
this.termOffset = termOffset;
return this;
}
/**
* Set the termOffset value to be what is in the {@link ChannelUri} which may be null.
*
* @param channelUri to read the value from.
* @return this for a fluent API.
* @see CommonContext#TERM_OFFSET_PARAM_NAME
*/
public ChannelUriStringBuilder termOffset(final ChannelUri channelUri)
{
final String termOffsetValue = channelUri.get(TERM_OFFSET_PARAM_NAME);
if (null == termOffsetValue)View on GitHub (pinned to 6d60124e15)