aeron-io/aeron · error · InvalidChannelException
MTU greater than max message length for term length: mtu=
Error message
MTU greater than max message length for term length: mtu={mtuLength} maxMessageLength={maxMessageLength} termLength={termLength} channel={channelUri} What it means
Aeron rejects a publication/subscription channel whose mtu-length exceeds the maximum message length derivable from the term buffer length (FrameDescriptor.computeMaxMessageLength, termLength minus framing header space). The driver throws InvalidChannelException in PublicationParams.getMtuLength because fragments larger than what a term buffer can frame could never be delivered. MTU must be <= maxMessageLength and is also typically a multiple of FrameDescriptor.FRAGMENT_ALIGNMENT (32).
Solutions
- Lower the mtu-length URI parameter so it is <= computeMaxMessageLength(term-length) (termLength - 32, aligned to 32 bytes).
- Increase term-length to at least mtu + framing overhead (e.g. mtu-length=16384 requires term-length of at least 64K in practice).
- Remove the explicit mtu-length parameter and let the driver default (ctx.publicationTermWindowLength / defaultMtuLength) apply.
- If the values come from code, validate with AeronThread-safe checks before addPublication: FrameDescriptor.computeMaxMessageLength(termLength) >= mtuLength.
Example fix
// before
Aeron.connect().addPublication("aeron:udp?endpoint=224.0.1.1:40456|term-length=64k|mtu-length=128k", 1);
// after (mtu fits within term length)
Aeron.connect().addPublication("aeron:udp?endpoint=224.0.1.1:40456|term-length=64k|mtu-length=16k", 1); Defensive patterns
Strategy: validation
Validate before calling
import static io.aeron.logbuffer.FrameDescriptor.computeMaxMessageLength;
void checkMtu(int mtuLength, int termLength) {
int max = computeMaxMessageLength(termLength);
if (mtuLength > max) {
throw new IllegalArgumentException("mtu-length=" + mtuLength + " exceeds maxMessageLength=" + max + " for term-length=" + termLength);
}
} Try / catch
try {
publication = aeron.addPublication(channel, streamId);
} catch (InvalidChannelException e) {
log.error("Rejecting channel config: {}", e.getMessage());
throw new ConfigException(channel, e);
} Prevention
- Always validate mtu-length <= termLength - 32 before building the URI
- Keep mtu-length a multiple of 32 (FRAGMENT_ALIGNMENT)
- Prefer driver defaults unless benchmarking showed a win
- Centralize term-length/mtu-length pairs in one config constant
When it happens
Trigger: Adding a publication or exclusive publication where the channel URI sets mtu-length (or the context default) larger than computeMaxMessageLength(term-length), e.g. mtu-length=16384 with term-length=16384, or a huge mtu-length like 1Mb with the default 64Kb term length.
Common situations: Copy-pasting an mtu-length from another transport config; setting term-length and mtu-length to the same value forgetting header overhead; tuning for throughput by raising MTU without raising term-length; Aeron-specific gotcha since MTU also must fit UDP datagram limits.
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- mtuLength= is not a multiple of FRAME_ALIGNMENT=
- mtuLength= > SO_SNDBUF= , increase to match MTU
- term-length= does not match session-id tag value: channel=
- EINVAL
- Aeron client instance must set…
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/bfc820dfc82e2fc1.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/PublicationParams.java:248
this.termLength = termLength;
}
}
private void getMtuLength(final ChannelUri channelUri)
{
final String mtuParam = channelUri.get(MTU_LENGTH_PARAM_NAME);
if (null != mtuParam)
{
final int mtuLength = (int)SystemUtil.parseSize(MTU_LENGTH_PARAM_NAME, mtuParam);
Configuration.validateMtuLength(mtuLength);
validateMtuLength(this, mtuLength, channelUri);
this.mtuLength = mtuLength;
}
final int maxMessageLength = FrameDescriptor.computeMaxMessageLength(termLength);
if (mtuLength > maxMessageLength)
{
throw new InvalidChannelException("MTU greater than max message length for term length: mtu=" +
mtuLength + " maxMessageLength=" + maxMessageLength + " termLength=" + termLength + " channel=" +
channelUri);
}
}
static void validateTermLength(
final PublicationParams params, final int explicitTermLength, final ChannelUri channelUri)
{
if (params.isSessionIdTagged && explicitTermLength != params.termLength)
{
throw new InvalidChannelException(
TERM_LENGTH_PARAM_NAME + "=" + explicitTermLength + " does not match session-id tag value: channel=" +
channelUri);
}
}
static void validateMtuLength(
final PublicationParams params, final int explicitMtuLength, final ChannelUri channelUri)View on GitHub (pinned to 6d60124e15)