{"record":{"id":"555ae205a4f3a467","repo":"apache/pulsar","slug":"watermark-interval-must-be-positive-watermarkem","errorCode":null,"errorMessage":"Watermark interval must be positive [${watermarkEmitIntervalMs}]","messagePattern":"Watermark interval must be positive \\[(.+?)\\]","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/WindowConfigUtils.java","lineNumber":75,"sourceCode":"        }\n\n        if (windowConfig.getSlidingIntervalDurationMs() != null) {\n            if (windowConfig.getSlidingIntervalDurationMs() <= 0) {\n                throw new IllegalArgumentException(\n                        \"Sliding interval must be positive [\" + windowConfig.getSlidingIntervalDurationMs() + \"]\");\n            }\n        }\n\n        if (windowConfig.getTimestampExtractorClassName() != null) {\n            if (windowConfig.getMaxLagMs() != null) {\n                if (windowConfig.getMaxLagMs() < 0) {\n                    throw new IllegalArgumentException(\n                            \"Lag duration must be positive [\" + windowConfig.getMaxLagMs() + \"]\");\n                }\n            }\n            if (windowConfig.getWatermarkEmitIntervalMs() != null) {\n                if (windowConfig.getWatermarkEmitIntervalMs() <= 0) {\n                    throw new IllegalArgumentException(\n                            \"Watermark interval must be positive [\" + windowConfig.getWatermarkEmitIntervalMs() + \"]\");\n                }\n            }\n        }\n    }\n\n    public static void inferMissingArguments(WindowConfig windowConfig) {\n        if (windowConfig.getWindowLengthDurationMs() != null && windowConfig.getSlidingIntervalDurationMs() == null) {\n            windowConfig.setSlidingIntervalDurationMs(windowConfig.getWindowLengthDurationMs());\n        }\n\n        if (windowConfig.getWindowLengthCount() != null && windowConfig.getSlidingIntervalCount() == null) {\n            windowConfig.setSlidingIntervalCount(windowConfig.getWindowLengthCount());\n        }\n\n        if (windowConfig.getTimestampExtractorClassName() != null) {\n            if (windowConfig.getMaxLagMs() == null) {\n                windowConfig.setMaxLagMs(DEFAULT_MAX_LAG_MS);","sourceCodeStart":57,"sourceCodeEnd":93,"githubUrl":"https://github.com/apache/pulsar/blob/820761864ed8e2a7d2e52dd9763ad2ae117c1395/pulsar-functions/utils/src/main/java/org/apache/pulsar/functions/utils/WindowConfigUtils.java#L57-L93","documentation":"WindowConfigUtils.validate(), inside the timestamp-extractor branch, requires watermarkEmitIntervalMs — how often watermarks are emitted downstream — to be a positive duration when provided. This IllegalArgumentException is thrown when the value is zero or negative, since a non-positive emit interval would make watermark generation degenerate.","triggerScenarios":"Calling WindowConfigUtils.validate(windowConfig) with a WindowConfig that has timestampExtractorClassName set and watermarkEmitIntervalMs <= 0 (e.g. 0L).","commonSituations":"Leaving a 0 placeholder in a generated/twelved config; unit-conversion bugs (seconds truncated to 0 ms); disabling watermark emission by setting 0 instead of removing the field.","solutions":["Set watermarkEmitIntervalMs to a positive value in milliseconds (e.g. 1000).","Set the field to null to use the engine default emit interval.","Validate the config with WindowConfigUtils.validate() before submission."],"exampleFix":"// before\nWindowConfig.builder().setTimestampExtractorClassName(MyExtractor.class.getName()).setWatermarkEmitIntervalMs(0).build();\n// after\nWindowConfig.builder().setTimestampExtractorClassName(MyExtractor.class.getName()).setWatermarkEmitIntervalMs(1000).build();","handlingStrategy":"validation","validationCode":"if (cfg.getTimestampExtractorClassName() != null && cfg.getWatermarkEmitIntervalMs() != null && cfg.getWatermarkEmitIntervalMs() <= 0) {\n    throw new IllegalArgumentException(\"watermarkEmitIntervalMs must be > 0, got \" + cfg.getWatermarkEmitIntervalMs());\n}","typeGuard":null,"tryCatchPattern":"try {\n    WindowConfigUtils.validate(windowConfig);\n} catch (IllegalArgumentException e) {\n    // reject submission with the validation message\n    throw e;\n}","preventionTips":["Omit the field (null) to use defaults instead of setting 0.","Compute intervals from Duration objects to avoid truncation to 0.","Add a unit test validating every WindowConfig template used in deployment."],"tags":["pulsar-functions","configuration","windowing","watermarks"],"backgroundTag":"config-validation-failed","analyzedSha":"820761864ed8e2a7d2e52dd9763ad2ae117c1395","analyzedAt":"2026-09-06T00:14:20.138Z","contentChangedAt":"2026-09-06T00:14:20.138Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}