aeron-io/aeron · error · IllegalArgumentException
gapLength must be smaller than gapRadix
Error message
gapLength must be smaller than gapRadix
What it means
MultiGapLossGenerator (a driver testing/loss-injection utility) constructs gaps aligned to a gapRadix that must be a positive power of two and strictly greater than gapLength. If gapLength >= the normalized gapRadix, the constructor throws IllegalArgumentException, because a gap cannot fit within the radix-aligned window it belongs to.
Solutions
- Set gapLength strictly smaller than gapRadix, e.g. gapLength=32 with gapRadix=64.
- Ensure gapRadix is a power of two (64, 128, 256...) so it is not rounded down below gapLength.
- Validate parameters before constructing: assert gapLength < BitUtil.findNextPositivePowerOfTwo(gapRadix).
- If you want gaps spanning the whole radix, increase gapRadix to the next power of two above gapLength.
Example fix
// before new MultiGapLossGenerator(termId, termLength, 64, 64, 3); // gapLength == gapRadix // after new MultiGapLossGenerator(termId, termLength, 32, 64, 3); // gapLength < gapRadix
Defensive patterns
Strategy: validation
Validate before calling
import io.aeron.driver.ext.MultiGapLossGenerator;
import org.agrona.BitUtil;
int radix = BitUtil.findNextPositivePowerOfTwo(gapRadix);
if (gapLength >= radix) {
throw new IllegalArgumentException(
"gapLength (" + gapLength + ") must be < next power of two of gapRadix (" + radix + ")");
} Try / catch
try {
new MultiGapLossGenerator(termId, termLength, gapLength, gapRadix, totalGaps);
} catch (IllegalArgumentException e) {
// correct gapLength/gapRadix values before retrying
} Prevention
- Always pick gapRadix as an explicit power of two (64, 128, 256).
- Keep gapLength at most half of gapRadix in test configs.
- Unit-test loss-generator parameters before wiring them into driver loss injection.
- Remember gapRadix is rounded down to the next power of two — pass exact powers of two to avoid surprises.
When it happens
Trigger: Constructing MultiGapLossGenerator with gapLength equal to or larger than gapRadix (e.g. gapLength=64, gapRadix=64), or with a gapRadix that is not a power of two (silently rounded down by findNextPositivePowerOfTwo, making actualGapRadix smaller than expected and smaller than gapLength).
Common situations: Configuring loss injection for testing with values like gapLength==gapRadix, or passing gapRadix=100 (rounded to 64) while gapLength stays at 80 — the rounding makes an otherwise-valid-looking configuration invalid.
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
- name + " cannot be negative: value=" + value
- Invalid errorBufferLength
- unsupported time unit
- ClusterMarkFile headerLength=
- invalid fileIoMaxLength=
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/c5a2bbbff48a308e.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-driver/src/main/java/io/aeron/driver/ext/MultiGapLossGenerator.java:56
/**
* Set the range of messages to be dropped.
*
* @param termId to be dropped
* @param gapRadix the initial offset and subsequent interval between gaps - must be a power of 2
* @param gapLength length of each gap
* @param totalGaps the total number of gaps
*/
public MultiGapLossGenerator(
final int termId,
final int gapRadix,
final int gapLength,
final int totalGaps)
{
final int actualGapRadix = BitUtil.findNextPositivePowerOfTwo(gapRadix);
if (gapLength >= actualGapRadix)
{
throw new IllegalArgumentException("gapLength must be smaller than gapRadix");
}
this.termId = termId;
this.gapRadixBits = Integer.numberOfTrailingZeros(actualGapRadix);
this.gapRadixMask = -actualGapRadix;
this.gapLength = gapLength;
this.lastGapLimit = (totalGaps * actualGapRadix) + gapLength;
}
/**
* {@inheritDoc}
*/
@Override
public boolean shouldDropFrame(final InetSocketAddress address, final UnsafeBuffer buffer, final int length)
{
return false;
}
View on GitHub (pinned to 6d60124e15)