{"record":{"id":"f48d2434fa2a01e9","repo":"apache/seatunnel","slug":"intervalms-must-be-positive-got-s","errorCode":null,"errorMessage":"intervalMs must be positive, got: %s","messagePattern":"intervalMs must be positive, got: (.+?)","errorType":"validation","errorClass":"IllegalArgumentException","httpStatus":null,"severity":"error","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/TaskExecutionService.java","lineNumber":1011,"sourceCode":"    }\n\n    /**\n     * Register or replace a periodic timer-flush task for one source subtask.\n     *\n     * <p>If a timer already exists for the same {@link TaskLocation}, cancel it first. The task is\n     * scheduled with fixed delay on {@code timerFlushWorker} and stored in {@code\n     * timerFlushFutures}.\n     *\n     * @param taskLocation source subtask location (map key)\n     * @param callback flush callback to run on each tick\n     * @param intervalMs flush interval in milliseconds, must be > 0\n     * @return scheduled future for later cancellation\n     * @throws IllegalArgumentException if intervalMs <= 0\n     */\n    public ScheduledFuture<?> registerTimerFlushTask(\n            TaskLocation taskLocation, Runnable callback, long intervalMs) {\n        if (intervalMs <= 0) {\n            throw new IllegalArgumentException(\"intervalMs must be positive, got: \" + intervalMs);\n        }\n        TaskGroupLocation groupLocation = taskLocation.getTaskGroupLocation();\n        ConcurrentMap<TaskLocation, ScheduledFuture<?>> groupFutures =\n                timerFlushFutures.computeIfAbsent(groupLocation, k -> new ConcurrentHashMap<>());\n\n        ScheduledFuture<?> existing = groupFutures.remove(taskLocation);\n        if (existing != null && !existing.isDone()) {\n            existing.cancel(false);\n        }\n\n        MDCScheduledExecutorService mdcTimerFlushWorker = MDCTracer.tracing(timerFlushWorker);\n        Runnable namedCallback = new NamedTaskWrapper(callback, \"TimerFlush-\" + taskLocation);\n        ScheduledFuture<?> future =\n                mdcTimerFlushWorker.scheduleWithFixedDelay(\n                        namedCallback, intervalMs, intervalMs, TimeUnit.MILLISECONDS);\n        groupFutures.put(taskLocation, future);\n        logger.info(\n                String.format(","sourceCodeStart":993,"sourceCodeEnd":1029,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/TaskExecutionService.java#L993-L1029","documentation":"registerTimerFlushTask validates that the timer flush interval (intervalMs) is strictly positive before scheduling the periodic flush task. A non-positive interval would create a useless or hot-looping scheduled task, so the constructor-level guard rejects it immediately with IllegalArgumentException.","triggerScenarios":"Calling TaskExecutionService.registerTimerFlushTask(taskLocation, callback, intervalMs) with intervalMs <= 0 — typically from a metrics/timer flush configuration resolved to 0, a negative value, or an uninitialized long default.","commonSituations":"Metrics flush interval set to 0 in job config believing 0 means 'disabled'; a config option typed as long whose default was never set; unit conversion bugs (seconds vs milliseconds) producing 0.","solutions":["Pass a strictly positive intervalMs, e.g. at least 1 ms; use a distinct flag to disable flushing instead of 0","Check the metrics/timer flush interval config option value and its default — fix the config or the default","Validate/clamp the interval at config-parse time (e.g. require >= 1000ms) so the error surfaces early with the config key","If converting units, verify the multiplier (e.g. seconds * 1000) so a 0 second value doesn't silently become 0 ms"],"exampleFix":"// before\nlong intervalMs = 0; // intended: disabled\ntaskExecutionService.registerTimerFlushTask(taskLocation, callback, intervalMs);\n\n// after\nlong intervalMs = metricsFlushIntervalMs; // from config\nif (intervalMs > 0) {\n    taskExecutionService.registerTimerFlushTask(taskLocation, callback, intervalMs);\n}","handlingStrategy":"validation","validationCode":"if (intervalMs == null || intervalMs <= 0) {\n    throw new IllegalArgumentException(\"intervalMs must be > 0, got: \" + intervalMs);\n}","typeGuard":"boolean isValidInterval(Long ms) { return ms != null && ms > 0; }","tryCatchPattern":null,"preventionTips":["Never use 0 to mean 'disabled' — use a boolean flag or omit the call","Validate interval config at parse time with a documented minimum","Double-check unit conversions (seconds -> milliseconds)"],"tags":["zeta-engine","timer","validation","illegal-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T21:17:11.552Z"}