{"record":{"id":"2e7357e433d11c81","repo":"MyCATApache/Mycat-Server","slug":"mycat-server-channel-has-been-closed","errorCode":null,"errorMessage":"MyCAT Server Channel has been closed","messagePattern":"MyCAT Server Channel has been closed","errorType":"exception","errorClass":"IllegalStateException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/mycat/net/AIOAcceptor.java","lineNumber":105,"sourceCode":"\tprivate void accept(NetworkChannel channel, Long id) {\n\t\ttry {\n\t\t\tFrontendConnection c = factory.make(channel);\n\t\t\tc.setAccepted(true);\n\t\t\tc.setId(id);\n\t\t\tNIOProcessor processor = MycatServer.getInstance().nextProcessor();\n\t\t\tc.setProcessor(processor);\n\t\t\tc.register();\n\t\t} catch (Exception e) {\n\t\t    LOGGER.error(\"AioAcceptorError\", e);\n\t\t\tcloseChannel(channel);\n\t\t}\n\t}\n\n\tprivate void pendingAccept() {\n\t\tif (serverChannel.isOpen()) {\n\t\t\tserverChannel.accept(ID_GENERATOR.getId(), this);\n\t\t} else {\n\t\t\tthrow new IllegalStateException(\n\t\t\t\t\t\"MyCAT Server Channel has been closed\");\n\t\t}\n\n\t}\n\n\t@Override\n\tpublic void completed(AsynchronousSocketChannel result, Long id) {\n\t\taccept(result, id);\n\t\t// next pending waiting\n\t\tpendingAccept();\n\n\t}\n\n\t@Override\n\tpublic void failed(Throwable exc, Long id) {\n\t\tLOGGER.info(\"acception connect failed:\" + exc);\n\t\t// next pending waiting\n\t\tpendingAccept();","sourceCodeStart":87,"sourceCodeEnd":123,"githubUrl":"https://github.com/MyCATApache/Mycat-Server/blob/65f8d8beb752f935752f2a0eec0ab017facab9ef/src/main/java/io/mycat/net/AIOAcceptor.java#L87-L123","documentation":"AIOAcceptor.pendingAccept re-arms the async server socket accept. If the server channel is no longer open (server shutting down or accept failed fatally), it throws IllegalStateException 'MyCAT Server Channel has been called' — actually 'closed' — so the accept loop stops instead of looping forever on a dead channel.","triggerScenarios":"Calling start/completed/failed handlers after the AIO server socket was closed (server shutdown, bind failure earlier, OS closed the descriptor); failed() invoked then pendingAccept attempted.","commonSituations":"Port already bound by another process causing bind failure then a stray accept; shutdown hooks closing the channel while in-flight completion callbacks run; OS-level network errors closing the listening socket.","solutions":["Check startup logs for a bind failure (address already in use) that left the channel closed; free the port and restart.","If seen during normal shutdown, it is expected noise — suppress or ignore logs during stop.","If seen at runtime without shutdown, verify no external process/admin closed the socket; restart MyCAT.","Review AIO transport choice: switching to NIO (frontend backend NIO config) avoids the AIO accept path entirely."],"exampleFix":"// before\nprivate void pendingAccept() {\n    if (serverChannel.isOpen()) {\n        serverChannel.accept(ID_GENERATOR.getId(), this);\n    } else {\n        throw new IllegalStateException(\"MyCAT Server Channel has been closed\");\n    }\n}\n// after\nprivate void pendingAccept() {\n    if (!serverChannel.isOpen()) {\n        LOGGER.warn(\"server channel closed, stop accepting\");\n        return; // graceful stop instead of throwing into the proactor thread\n    }\n    serverChannel.accept(ID_GENERATOR.getId(), this);\n}","handlingStrategy":"try-catch","validationCode":"// before starting AIO server, check the port is free\ntry (ServerSocket probe = new ServerSocket()) {\n    probe.bind(new InetSocketAddress(port));\n} catch (IOException e) { throw new IllegalStateException(\"port \" + port + \" in use\"); }","typeGuard":null,"tryCatchPattern":"try { server.start(); } catch (IllegalStateException e) {\n    if (e.getMessage().contains(\"Channel has been closed\")) {\n        // treat as shutdown noise or bind failure; check startup logs, restart if needed\n    }\n}","preventionTips":["Ensure the listen port is free before startup (ss -ltnp | grep <port>)","Ignore/expect this error during orderly shutdown","Avoid closing the server channel while accept callbacks are in flight","Consider NIO transport if AIO lifecycle issues recur"],"tags":["aio","network","server-shutdown","accept"],"backgroundTag":"invalid-state-transition","analyzedSha":"65f8d8beb752f935752f2a0eec0ab017facab9ef","analyzedAt":"2026-09-11T00:12:21.696Z","contentChangedAt":"2026-09-11T00:12:21.696Z","schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}