{"record":{"id":"76a9887423902270","repo":"apache/seatunnel","slug":"edge-socket-tcp-server-is-already-running-skip-du","errorCode":null,"errorMessage":"Edge socket TCP server is already running, skip duplicate start","messagePattern":"Edge socket TCP server is already running, skip duplicate start","errorType":"console","errorClass":null,"httpStatus":null,"severity":"info","filePath":"seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/source/EdgeSocketIngressServer.java","lineNumber":64,"sourceCode":"    private final Object lifecycleLock = new Object();\n\n    private volatile ServerSocket serverSocket;\n    private volatile ExecutorService receiverExecutor;\n    private volatile Future<?> receiverFuture;\n    private volatile RuntimeException fatalReceiverException;\n    private volatile boolean hasActiveCollector;\n    private int remainingOpenRetries;\n\n    public EdgeSocketIngressServer(EdgeSocketConfig config, IncomingRecordHandler handler) {\n        this.config = config;\n        this.protocolHandler = new IngressProtocolHandler(config, handler);\n    }\n\n    /** Start the TCP server and begin accepting collector connections. */\n    public void start() {\n        synchronized (lifecycleLock) {\n            if (isReceiverAlive()) {\n                log.warn(\"Edge socket TCP server is already running, skip duplicate start\");\n                return;\n            }\n            fatalReceiverException = null;\n            remainingOpenRetries = config.getMaxNumRetries();\n            startReceiverLoop();\n        }\n    }\n\n    /** Stop the TCP server and shut down the receiver thread. */\n    public void stop() throws IOException {\n        closeServerSocket();\n        synchronized (lifecycleLock) {\n            stopReceiverLoop();\n        }\n    }\n\n    public boolean isListening() {\n        ServerSocket ss = serverSocket;","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/apache/seatunnel/blob/cf67b549a7a6c35fa0beb12d83c62892427ea919/seatunnel-connectors-v2/connector-edge-socket/src/main/java/org/apache/seatunnel/connectors/seatunnel/edgesocket/source/EdgeSocketIngressServer.java#L46-L82","documentation":"Warned by EdgeSocketIngressServer.start() when the TCP server is asked to start while a receiver thread is already alive. The call is a no-op (idempotent) rather than throwing, preventing accidental double-binding of the port. It signals redundant lifecycle calls in caller code.","triggerScenarios":"start() called twice without an intervening stop() — e.g. lifecycle start triggered again after a reopen/retry, or test/setup code invoking start() per-case without teardown.","commonSituations":"Source reader lifecycle hooks both initializing and starting the server, retry logic restarting the loop without recognizing it is still alive, tests with shared server instances.","solutions":["Guard caller code so start() is invoked once per server lifecycle, or rely on this idempotency and treat it as expected.","Track started state in the owning component instead of calling start() unconditionally.","In tests, stop the server in @AfterEach/tearDown before the next start()."],"exampleFix":"// before\nserver.start(); server.start(); // duplicate\n// after\nif (!server.isRunning()) { server.start(); }","handlingStrategy":"type-guard","validationCode":"if (!server.isReceiverAlive()) { server.start(); }","typeGuard":"function canStart(server) { return typeof server.isReceiverAlive === 'function' && !server.isReceiverAlive(); }","tryCatchPattern":null,"preventionTips":["Own start/stop in one lifecycle component","Treat start() as idempotent and this warning as expected if lifecycle can race","In tests, always stop() in teardown"],"tags":["lifecycle","idempotent","duplicate-start"],"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-23T08:17:48.524Z"}