{"record":{"id":"c3cad0e6623e4e5a","repo":"spring-projects/spring-boot","slug":"socket-is-closed","errorCode":null,"errorMessage":"Socket is closed","messagePattern":"Socket is closed","errorType":"exception","errorClass":"SocketException","httpStatus":null,"severity":"error","filePath":"buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/socket/UnixDomainSocket.java","lineNumber":59,"sourceCode":"\t * @throws IOException if the socket cannot be opened\n\t */\n\tpublic static Socket get(String path) throws IOException {\n\t\treturn new UnixDomainSocket(path);\n\t}\n\n\tprivate final SocketAddress socketAddress;\n\n\tprivate final SocketChannel socketChannel;\n\n\tprivate UnixDomainSocket(String path) throws IOException {\n\t\tthis.socketAddress = UnixDomainSocketAddress.of(path);\n\t\tthis.socketChannel = SocketChannel.open(this.socketAddress);\n\t}\n\n\t@Override\n\tpublic InputStream getInputStream() throws IOException {\n\t\tif (isClosed()) {\n\t\t\tthrow new SocketException(\"Socket is closed\");\n\t\t}\n\t\tif (!isConnected()) {\n\t\t\tthrow new SocketException(\"Socket is not connected\");\n\t\t}\n\t\tif (isInputShutdown()) {\n\t\t\tthrow new SocketException(\"Socket input is shutdown\");\n\t\t}\n\n\t\treturn Channels.newInputStream(this.socketChannel);\n\t}\n\n\t@Override\n\tpublic OutputStream getOutputStream() throws IOException {\n\t\tif (isClosed()) {\n\t\t\tthrow new SocketException(\"Socket is closed\");\n\t\t}\n\t\tif (!isConnected()) {\n\t\t\tthrow new SocketException(\"Socket is not connected\");","sourceCodeStart":41,"sourceCodeEnd":77,"githubUrl":"https://github.com/spring-projects/spring-boot/blob/270dfe353fb830fd69b823a8a859287ff103854b/buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/socket/UnixDomainSocket.java#L41-L77","documentation":"UnixDomainSocket.getInputStream (and getOutputStream) check isClosed() first and throw SocketException('Socket is closed') if the socket has been closed. This mirrors the contract of java.net.Socket. The socket is closed by close() (which also closes the underlying SocketChannel). Any subsequent attempt to obtain a stream fails.","triggerScenarios":"getInputStream() or getOutputStream() is called after close() ran — either an explicit close() call or a try-with-resources that exited.","commonSituations":"A try-with-resources around the socket followed by a read outside the block; a connection pool evicting and closing an idle socket while another thread still holds a reference; double-close.","solutions":["Do not use the socket after close(); move all I/O inside the socket's try-with-resources block.","If the socket is pooled, reopen it via UnixDomainSocket.get(path) after eviction.","Audit for double-close or shared references that close out from under a reader."],"exampleFix":"// before\ntry (Socket s = UnixDomainSocket.get(path)) {\n    // ...\n}\nreturn s.getInputStream(); // throws \"Socket is closed\"\n// after\ntry (Socket s = UnixDomainSocket.get(path);\n     InputStream in = s.getInputStream()) {\n    // read here\n}","handlingStrategy":"validation","validationCode":"// Guard before obtaining a stream\nif (socket.isClosed()) {\n    socket = UnixDomainSocket.get(path); // reopen\n}\nInputStream in = socket.getInputStream();","typeGuard":null,"tryCatchPattern":"try {\n    socket.getInputStream();\n} catch (java.net.SocketException ex) {\n    if (\"Socket is closed\".equals(ex.getMessage())) {\n        socket = UnixDomainSocket.get(path); // reopen and retry once\n    } else throw ex;\n}","preventionTips":["Scope all I/O within the socket's try-with-resources block.","Never share a socket across closers in different threads.","After closing a pooled socket, drop all references that could read from it."],"tags":["docker","socket","unix-domain-socket","buildpack"],"backgroundTag":null,"analyzedSha":"270dfe353fb830fd69b823a8a859287ff103854b","analyzedAt":"2026-08-11T19:42:06.541Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}