elastic/elasticsearch · error · IllegalArgumentException
staleTime must be a positive duration but was [${staleTime}]
Error message
staleTime must be a positive duration but was [${staleTime}] What it means
The AsyncWebIdentityCredentialsProvider builder rejects a staleTime Duration that is zero or negative. staleTime defines how long before credential expiry a cached entry is considered stale and triggers refresh; a non-positive value would never allow staleness. The check runs in the private constructor after defaults are applied.
Source
Thrown at libs/workload-identity-aws/src/main/java/org/elasticsearch/workload/identity/aws/AsyncWebIdentityCredentialsProvider.java:95
private final Consumer<ActionListener<String>> tokenSupplier;
private final StsAsyncClient stsAsyncClient;
private final Duration prefetchTime;
private final Duration staleTime;
private final Clock clock;
private final AtomicReference<Cached> cache = new AtomicReference<>();
private final AtomicReference<CompletableFuture<Cached>> inFlight = new AtomicReference<>();
private AsyncWebIdentityCredentialsProvider(Builder builder) {
this.roleArn = Objects.requireNonNull(builder.roleArn, "roleArn must not be null");
this.roleSessionName = Objects.requireNonNull(builder.roleSessionName, "roleSessionName must not be null");
this.tokenSupplier = Objects.requireNonNull(builder.tokenSupplier, "tokenSupplier must not be null");
this.stsAsyncClient = Objects.requireNonNull(builder.stsAsyncClient, "stsAsyncClient must not be null");
this.prefetchTime = builder.prefetchTime != null ? builder.prefetchTime : DEFAULT_PREFETCH_TIME;
this.staleTime = builder.staleTime != null ? builder.staleTime : DEFAULT_STALE_TIME;
this.clock = builder.clock != null ? builder.clock : Clock.systemUTC();
if (staleTime.isNegative() || staleTime.isZero()) {
throw new IllegalArgumentException("staleTime must be a positive duration but was [" + staleTime + "]");
}
if (prefetchTime.isNegative() || prefetchTime.isZero()) {
throw new IllegalArgumentException("prefetchTime must be a positive duration but was [" + prefetchTime + "]");
}
// prefetchTime must start no later than staleTime, otherwise prefetchAt would fall after staleAt and the
// background-refresh window in resolveIdentity() would be unreachable.
if (prefetchTime.compareTo(staleTime) < 0) {
throw new IllegalArgumentException(
"prefetchTime [" + prefetchTime + "] must be greater than or equal to staleTime [" + staleTime + "]"
);
}
}
public static Builder builder() {
return new Builder();
}
@OverrideView on GitHub (pinned to db6a809a66)
Solutions
- Set staleTime to a positive Duration (e.g. Duration.ofMinutes(5))
- If you want aggressive refresh, use a small positive value, not zero
- Validate config-sourced durations before passing to the builder
Example fix
// before .provider.staleTime(Duration.ZERO).build() // after .provider.staleTime(Duration.ofSeconds(30)).build()
Defensive patterns
Strategy: validation
Validate before calling
if (staleTime == null || staleTime.isZero() || staleTime.isNegative()) {
throw new IllegalArgumentException("staleTime must be positive: " + staleTime);
}
builder.staleTime(staleTime); Type guard
static boolean isPositiveDuration(Duration d) {
return d != null && !d.isZero() && !d.isNegative();
} Try / catch
try { builder.staleTime(d).build(); }
catch (IllegalArgumentException e) { /* use default */ } Prevention
- Treat 0 as invalid, not as 'always refresh'
- Validate config-sourced durations before builder call
- Document the units (Duration) in the config key
When it happens
Trigger: Building the provider with .staleTime(Duration.ofSeconds(0)) or a negative Duration. The default (DEFAULT_STALE_TIME) is used when null, so this only fires when an explicit non-positive Duration is supplied.
Common situations: Computing staleTime from a config knob typed as 0; passing Duration.ZERO meaning "refresh immediately"; mis-tuning refresh windows; arithmetic that produces a negative duration when expiry is near.
Related errors
- prefetchTime must be a positive duration but was [${prefetch
- prefetchTime [${prefetchTime}] must be greater than or equal
- starting java failed with [%d] output: %s error: %s
- CONFIG
- could not resolve ssl client verification mode, unknown valu
AI-assisted analysis of elastic/elasticsearch@db6a809a66 (2026-08-12).
Data as JSON: /api/errors/aa69fbf7c23cbd64.
Report an issue: GitHub.