aeron-io/aeron · error · IllegalArgumentException
newLeaderTimeoutNs must be positive or -1, but was
Error message
newLeaderTimeoutNs must be positive or -1, but was <newLeaderTimeoutNs>
What it means
newLeaderTimeoutNs controls how long the client waits for a new leader before failing. Context.newLeaderTimeoutNs() validates the value with IllegalArgumentException: it must be strictly positive or the NULL_VALUE (-1) sentinel meaning use the default; zero and other negatives are rejected.
Solutions
- Pass a positive value in nanoseconds, e.g. TimeUnit.SECONDS.toNanos(30)
- Pass AeronCluster.NULL_VALUE (-1) to accept the library default
- Fix config parsing so 0/negative inputs map to the default rather than being forwarded
Example fix
// before long timeout = config.getTimeoutMs(); // may be 0 ctx.newLeaderTimeoutNs(timeout); // after long timeoutMs = config.getTimeoutMs(); long timeoutNs = timeoutMs > 0 ? TimeUnit.MILLISECONDS.toNanos(timeoutMs) : AeronCluster.NULL_VALUE; ctx.newLeaderTimeoutNs(timeoutNs);
Defensive patterns
Strategy: validation
Validate before calling
long ns = configuredTimeout;
if (!(ns > 0 || ns == AeronCluster.NULL_VALUE)) {
throw new IllegalArgumentException("newLeaderTimeoutNs must be positive or NULL_VALUE(-1), got " + ns);
}
ctx.newLeaderTimeoutNs(ns); Prevention
- Map unit conversions so a 0 or unset timeout becomes NULL_VALUE (default) rather than 0
- Validate timeout config (unit, sign) at load time
When it happens
Trigger: Calling ctx.newLeaderTimeoutNs(0) or any negative value other than -1 (NULL_VALUE).
Common situations: Passing a timeout in different units that rounds to 0; using 0 to mean 'no wait' (not supported); computing the value from config where 0/null handling goes wrong.
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.
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- publicationUnblockTimeoutNs=
- clientLivenessTimeoutNs=
- untetheredLingerTimeoutNs=
- invalid fileIoMaxLength=
- segment file length not a power of 2
AI-assisted analysis of aeron-io/aeron@6d60124e15 (2026-09-12).
Data as JSON: /api/errors/71fe4338130e569c.
Report an issue: GitHub.
Appendix: source
Thrown at aeron-cluster/src/main/java/io/aeron/cluster/client/AeronCluster.java:1600
@Config
public long messageTimeoutNs()
{
return CommonContext.checkDebugTimeout(messageTimeoutNs, TimeUnit.NANOSECONDS);
}
/**
* The timeout to wait for a new leader after noticing a disconnection from the previous one. Upon timeout the
* cluster will be considered lost and the client will close. If set to {@link Aeron#NULL_VALUE}, a reasonable
* default will be used.
*
* @param newLeaderTimeoutNs the new leader timeout in nanoseconds or {@link Aeron#NULL_VALUE}.
* @return this for a fluent API.
*/
public Context newLeaderTimeoutNs(final long newLeaderTimeoutNs)
{
if (!(0 < newLeaderTimeoutNs || NULL_VALUE == newLeaderTimeoutNs))
{
throw new IllegalArgumentException(
"newLeaderTimeoutNs must be positive or -1, but was " + newLeaderTimeoutNs);
}
this.newLeaderTimeoutNs = newLeaderTimeoutNs;
return this;
}
/**
* The timeout to wait for a new leader after noticing a disconnection from the previous one. Upon timeout the
* cluster will be considered lost and the client will close.
*
* @return the new leader timeout in nanoseconds.
*/
public long newLeaderTimeoutNs()
{
return CommonContext.checkDebugTimeout(newLeaderTimeoutNs, TimeUnit.NANOSECONDS);
}
/**View on GitHub (pinned to 6d60124e15)