{"record":{"id":"8729a476ad5958a1","repo":"aeron-io/aeron","slug":"publicationunblocktimeoutns-publicationunblocktimeoutns","errorCode":null,"errorMessage":"publicationUnblockTimeoutNs=${publicationUnblockTimeoutNs} <= clientLivenessTimeoutNs=${clientLivenessTimeoutNs}","messagePattern":"publicationUnblockTimeoutNs=(.+?) <= clientLivenessTimeoutNs=(.+?)","errorType":"validation","errorClass":"ConfigurationException","httpStatus":null,"severity":"error","filePath":"aeron-driver/src/main/java/io/aeron/driver/Configuration.java","lineNumber":2598,"sourceCode":"    public static int countersMetadataBufferLength(final int counterValuesBufferLength)\n    {\n        return counterValuesBufferLength * (CountersReader.METADATA_LENGTH / CountersReader.COUNTER_LENGTH);\n    }\n\n    /**\n     * Validate that the timeouts for unblocking publications from a client are valid.\n     *\n     * @param publicationUnblockTimeoutNs after which an uncommitted publication will be unblocked.\n     * @param clientLivenessTimeoutNs     after which a client will be considered not alive.\n     * @param timerIntervalNs             interval at which the driver will check timeouts.\n     * @throws ConfigurationException if the values are not valid.\n     */\n    public static void validateUnblockTimeout(\n        final long publicationUnblockTimeoutNs, final long clientLivenessTimeoutNs, final long timerIntervalNs)\n    {\n        if (publicationUnblockTimeoutNs <= clientLivenessTimeoutNs)\n        {\n            throw new ConfigurationException(\n                \"publicationUnblockTimeoutNs=\" + publicationUnblockTimeoutNs +\n                \" <= clientLivenessTimeoutNs=\" + clientLivenessTimeoutNs);\n        }\n\n        if (clientLivenessTimeoutNs <= timerIntervalNs)\n        {\n            throw new ConfigurationException(\n                \"clientLivenessTimeoutNs=\" + clientLivenessTimeoutNs +\n                \" <= timerIntervalNs=\" + timerIntervalNs);\n        }\n    }\n\n    /**\n     * Validate that the timeouts for untethered subscriptions are greater than timer interval.\n     *\n     * @param untetheredWindowLimitTimeoutNs after which an active untethered subscription will be lingered.\n     * @param untetheredLingerTimeoutNs      after which a lingering untethered subscription will transition to resting.\n     * @param untetheredRestingTimeoutNs     after which a resting untethered subscription will become active again.","sourceCodeStart":2580,"sourceCodeEnd":2616,"githubUrl":"https://github.com/aeron-io/aeron/blob/6d60124e15e35c11b49ba2e3c2c2858a09a18803/aeron-driver/src/main/java/io/aeron/driver/Configuration.java#L2580-L2616","documentation":"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.","triggerScenarios":"Calling validateUnblockTimeout (during DriverContext conclusion) with aeron.publication.unblock.timeout <= aeron.client.liveness.timeout, e.g. publicationUnblockTimeoutNs=5s and clientLivenessTimeoutNs=10s.","commonSituations":"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'.","solutions":["Raise aeron.publication.unblock.timeout so it is strictly greater than aeron.client.liveness.timeout","Or lower aeron.client.liveness.timeout below the unblock timeout","Re-derive all timeouts together: timerInterval < clientLiveness < publicationUnblock"],"exampleFix":"// before\nctx.clientLivenessTimeoutNs(TimeUnit.SECONDS.toNanos(10));\nctx.publicationUnblockTimeoutNs(TimeUnit.SECONDS.toNanos(5));\n// after\nctx.clientLivenessTimeoutNs(TimeUnit.SECONDS.toNanos(10));\nctx.publicationUnblockTimeoutNs(TimeUnit.SECONDS.toNanos(15)); // > clientLivenessTimeout","handlingStrategy":"validation","validationCode":"long liveness = TimeUnit.SECONDS.toNanos(10);\nlong unblock = TimeUnit.SECONDS.toNanos(15);\nlong timer = TimeUnit.MILLISECONDS.toNanos(100);\nif (unblock <= liveness) throw new IllegalStateException(\"publicationUnblockTimeout must be > clientLivenessTimeout\");\nio.aeron.driver.Configuration.validateUnblockTimeout(unblock, liveness, timer);","typeGuard":null,"tryCatchPattern":"try {\n    ctx.conclude();\n} catch (ConfigurationException e) {\n    if (e.getMessage().contains(\"publicationUnblockTimeoutNs\")) {\n        ctx.publicationUnblockTimeoutNs(ctx.clientLivenessTimeoutNs() * 2);\n        ctx.conclude();\n    } else { throw e; }\n}","preventionTips":["Define all timeouts in one place with the invariant timerInterval < clientLiveness < publicationUnblock","When changing one timeout, re-validate the whole set","Add a config lint check in CI for timeout ordering"],"tags":["aeron","configuration","timeout","validation"],"backgroundTag":"conflicting-config-options","analyzedSha":"6d60124e15e35c11b49ba2e3c2c2858a09a18803","analyzedAt":"2026-09-12T11:17:07.683Z","contentChangedAt":"2026-09-12T11:17:07.683Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}