aeron-io/aeron · error · ConfigurationException

publicationUnblockTimeoutNs=

Error message

publicationUnblockTimeoutNs=${publicationUnblockTimeoutNs} <= clientLivenessTimeoutNs=${clientLivenessTimeoutNs}

What it means

Configuration.validateUnblockTimeout enforces that the publication unblock timeout is strictly greater than the client liveness timeout; otherwise the driver could unblock/timeout a publication for a client that is still considered live, breaking liveness semantics. A ConfigurationException is thrown when publicationUnblockTimeoutNs <= clientLivenessTimeoutNs.

Solutions

  1. Raise aeron.publication.unblock.timeout so it is strictly greater than aeron.client.liveness.timeout
  2. Or lower aeron.client.liveness.timeout below the unblock timeout
  3. Re-derive all timeouts together: timerInterval < clientLiveness < publicationUnblock

Example fix

// before
ctx.clientLivenessTimeoutNs(TimeUnit.SECONDS.toNanos(10));
ctx.publicationUnblockTimeoutNs(TimeUnit.SECONDS.toNanos(5));
// after
ctx.clientLivenessTimeoutNs(TimeUnit.SECONDS.toNanos(10));
ctx.publicationUnblockTimeoutNs(TimeUnit.SECONDS.toNanos(15)); // > clientLivenessTimeout
Defensive patterns

Strategy: validation

Validate before calling

long liveness = TimeUnit.SECONDS.toNanos(10);
long unblock = TimeUnit.SECONDS.toNanos(15);
long timer = TimeUnit.MILLISECONDS.toNanos(100);
if (unblock <= liveness) throw new IllegalStateException("publicationUnblockTimeout must be > clientLivenessTimeout");
io.aeron.driver.Configuration.validateUnblockTimeout(unblock, liveness, timer);

Try / catch

try {
    ctx.conclude();
} catch (ConfigurationException e) {
    if (e.getMessage().contains("publicationUnblockTimeoutNs")) {
        ctx.publicationUnblockTimeoutNs(ctx.clientLivenessTimeoutNs() * 2);
        ctx.conclude();
    } else { throw e; }
}

Prevention

When it happens

Trigger: Calling validateUnblockTimeout (during DriverContext conclusion) with aeron.publication.unblock.timeout <= aeron.client.liveness.timeout, e.g. publicationUnblockTimeoutNs=5s and clientLivenessTimeoutNs=10s.

Common situations: Tuning client liveness timeout up (for slow/quiet clients) without revisiting the unblock timeout; copying individual timeout properties from different example configs; shrinking the unblock timeout to 'free stuck publications faster'.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12). Data as JSON: /api/errors/8729a476ad5958a1. Report an issue: GitHub.

Appendix: source

Thrown at aeron-driver/src/main/java/io/aeron/driver/Configuration.java:2598

    public static int countersMetadataBufferLength(final int counterValuesBufferLength)
    {
        return counterValuesBufferLength * (CountersReader.METADATA_LENGTH / CountersReader.COUNTER_LENGTH);
    }

    /**
     * Validate that the timeouts for unblocking publications from a client are valid.
     *
     * @param publicationUnblockTimeoutNs after which an uncommitted publication will be unblocked.
     * @param clientLivenessTimeoutNs     after which a client will be considered not alive.
     * @param timerIntervalNs             interval at which the driver will check timeouts.
     * @throws ConfigurationException if the values are not valid.
     */
    public static void validateUnblockTimeout(
        final long publicationUnblockTimeoutNs, final long clientLivenessTimeoutNs, final long timerIntervalNs)
    {
        if (publicationUnblockTimeoutNs <= clientLivenessTimeoutNs)
        {
            throw new ConfigurationException(
                "publicationUnblockTimeoutNs=" + publicationUnblockTimeoutNs +
                " <= clientLivenessTimeoutNs=" + clientLivenessTimeoutNs);
        }

        if (clientLivenessTimeoutNs <= timerIntervalNs)
        {
            throw new ConfigurationException(
                "clientLivenessTimeoutNs=" + clientLivenessTimeoutNs +
                " <= timerIntervalNs=" + timerIntervalNs);
        }
    }

    /**
     * Validate that the timeouts for untethered subscriptions are greater than timer interval.
     *
     * @param untetheredWindowLimitTimeoutNs after which an active untethered subscription will be lingered.
     * @param untetheredLingerTimeoutNs      after which a lingering untethered subscription will transition to resting.
     * @param untetheredRestingTimeoutNs     after which a resting untethered subscription will become active again.

View on GitHub (pinned to 6d60124e15)