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

  1. Set gapLength strictly smaller than gapRadix, e.g. gapLength=32 with gapRadix=64.
  2. Ensure gapRadix is a power of two (64, 128, 256...) so it is not rounded down below gapLength.
  3. Validate parameters before constructing: assert gapLength < BitUtil.findNextPositivePowerOfTwo(gapRadix).
  4. 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

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


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)