apache/pulsar · error · IllegalArgumentException
Lag duration must be positive [${maxLagMs}]
Error message
Lag duration must be positive [${maxLagMs}] What it means
WindowConfigUtils.validate() checks watermark/lag settings when a timestampExtractorClassName is configured. maxLagMs bounds how late events may arrive relative to the watermark; this IllegalArgumentException is thrown when maxLagMs is provided and is negative. (Zero is allowed here — the check is `< 0`, unlike other interval checks.)
Source
Thrown at pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/WindowConfigUtils.java:69
if (windowConfig.getSlidingIntervalCount() != null) {
if (windowConfig.getSlidingIntervalCount() <= 0) {
throw new IllegalArgumentException(
"Sliding interval must be positive [" + windowConfig.getSlidingIntervalCount() + "]");
}
}
if (windowConfig.getSlidingIntervalDurationMs() != null) {
if (windowConfig.getSlidingIntervalDurationMs() <= 0) {
throw new IllegalArgumentException(
"Sliding interval must be positive [" + windowConfig.getSlidingIntervalDurationMs() + "]");
}
}
if (windowConfig.getTimestampExtractorClassName() != null) {
if (windowConfig.getMaxLagMs() != null) {
if (windowConfig.getMaxLagMs() < 0) {
throw new IllegalArgumentException(
"Lag duration must be positive [" + windowConfig.getMaxLagMs() + "]");
}
}
if (windowConfig.getWatermarkEmitIntervalMs() != null) {
if (windowConfig.getWatermarkEmitIntervalMs() <= 0) {
throw new IllegalArgumentException(
"Watermark interval must be positive [" + windowConfig.getWatermarkEmitIntervalMs() + "]");
}
}
}
}
public static void inferMissingArguments(WindowConfig windowConfig) {
if (windowConfig.getWindowLengthDurationMs() != null && windowConfig.getSlidingIntervalDurationMs() == null) {
windowConfig.setSlidingIntervalDurationMs(windowConfig.getWindowLengthDurationMs());
}
if (windowConfig.getWindowLengthCount() != null && windowConfig.getSlidingIntervalCount() == null) {View on GitHub (pinned to 820761864e)
Solutions
- Set windowConfig.maxLagMs to a non-negative value (0 for no allowed lag, or a positive bound like 60000).
- Remove maxLagMs (set to null) to use the default if you did not intend to bound lateness.
- Guard the computed value: clamp with Math.max(0, computedLagMs) before building the config.
Example fix
// before WindowConfig.builder().setTimestampExtractorClassName(MyExtractor.class.getName()).setMaxLagMs(-1).build(); // after WindowConfig.builder().setTimestampExtractorClassName(MyExtractor.class.getName()).setMaxLagMs(60000).build();
Defensive patterns
Strategy: validation
Validate before calling
if (cfg.getTimestampExtractorClassName() != null && cfg.getMaxLagMs() != null && cfg.getMaxLagMs() < 0) {
throw new IllegalArgumentException("maxLagMs must be >= 0, got " + cfg.getMaxLagMs());
} Try / catch
try {
WindowConfigUtils.validate(windowConfig);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException("Fix maxLagMs: " + e.getMessage(), e);
} Prevention
- Clamp computed lag values with Math.max(0, value).
- Don't use negative sentinels for 'unbounded' lag; omit the field instead.
- When enabling a timestamp extractor, review all related fields (maxLagMs, watermarkEmitIntervalMs) together.
When it happens
Trigger: Calling WindowConfigUtils.validate(windowConfig) on a WindowConfig that sets timestampExtractorClassName and has maxLagMs < 0 (e.g. -1L).
Common situations: Using -1 as a sentinel for 'unbounded' or 'unset' lag in handwritten configs; computing the lag as a difference (current - event time) that went negative due to clock skew; copying a config template where the lag placeholder was negative.
Understand the failure class
Background: Config validation failed: what "invalid value for {key}" and settings-rejection errors mean across 19 open-source libraries — this error's family across 19 libraries.
Related errors
- Watermark interval must be positive [${watermarkEmitInterval
- Windows Function not support delivery semantics.
- Cannot enable auto ack when using windowing functionality
- Window length is not specified
- Window length for time and count are set! Please set one or
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/5d02a3dd8f888148.
Report an issue: GitHub.