{"record":{"id":"9ddc7350c9da5625","repo":"apache/seatunnel","slug":"scheduler-timed-out-during-close-relying-on-local","errorCode":null,"errorMessage":"Scheduler timed out during close; relying on local buffer as fallback. Could not determine dropped event count: {}","messagePattern":"Scheduler timed out during close; relying on local buffer as fallback\\. Could not determine dropped event count: (.+?)","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/event/JobEventLocalFileHandler.java","lineNumber":430,"sourceCode":"            try {\n                finallyTerminated = scheduledExecutorService.awaitTermination(2, TimeUnit.SECONDS);\n            } catch (InterruptedException e) {\n                Thread.currentThread().interrupt();\n            }\n            // Log how many ringbuffer events may have been skipped for observability.\n            try {\n                long tail = ringbuffer.tailSequence();\n                long unsynced = tail - committedEventIndex + 1;\n                if (unsynced > 0) {\n                    log.warn(\n                            \"Scheduler timed out during close; up to {} ringbuffer event(s) were\"\n                                    + \" not flushed to disk. Local buffer (cap={}) will be drained\"\n                                    + \" as fallback.\",\n                            unsynced,\n                            LOCAL_EVENT_BUFFER_CAPACITY);\n                }\n            } catch (Exception e) {\n                log.warn(\n                        \"Scheduler timed out during close; relying on local buffer as fallback.\"\n                                + \" Could not determine dropped event count: {}\",\n                        e.getMessage());\n            }\n            if (!finallyTerminated) {\n                // The scheduler thread is still alive even after shutdownNow().  Draining\n                // the local buffer here would race with the scheduler on writerLock.\n                // closing=true already prevents the scheduler from opening new files,\n                // so we can safely close the current writer under the lock and return.\n                log.warn(\n                        \"Scheduler thread did not terminate after shutdownNow();\"\n                                + \" skipping local buffer drain to avoid concurrent writer access.\");\n                synchronized (writerLock) {\n                    TraceFileWriter writer = currentWriter;\n                    currentWriter = null;\n                    if (writer != null) {\n                        try {\n                            writer.close();","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-engine/seatunnel-engine-server/src/main/java/org/apache/seatunnel/engine/server/event/JobEventLocalFileHandler.java#L412-L448","documentation":"A companion warning to the unsynced-count warning: when computing how many ring buffer events were skipped during a timed-out close(), an exception occurred (e.g. HazelcastInstanceNotActiveException because the ring buffer is already gone), so the handler logs that it cannot determine the dropped count and will rely on the local buffer fallback.","triggerScenarios":"close() times out waiting for the scheduler, then tailSequence() or committedEventIndex access throws — typically because Hazelcast is shutting down and the ring buffer proxy is no longer valid.","commonSituations":"Cluster shutdown ordering where the event handler closes after the Hazelcast instance is destroyed.","solutions":["Accept — this is a best-effort observability path; the local buffer drain is the fallback.","Close the JobEventLocalFileHandler before tearing down the Hazelcast instance to preserve accurate flush accounting.","Check shutdown hooks ordering in custom launchers that may close resources out of order."],"exampleFix":"null","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try { long tail = ringbuffer.tailSequence(); } catch (HazelcastInstanceNotActiveException e) { /* instance gone; rely on local buffer */ }","preventionTips":["Close event handlers before destroying the Hazelcast instance.","Treat observability accounting as best-effort during shutdown."],"tags":["shutdown","hazelcast","observability"],"backgroundTag":"invalid-state-transition","analyzedSha":"cf67b549a7a6c35fa0beb12d83c62892427ea919","analyzedAt":"2026-09-10T21:44:55.265Z","contentChangedAt":"2026-09-10T21:44:55.265Z","schemaVersion":2},"datasetVersion":"2026-09-14T11:17:12.474Z"}