spring-projects/spring-boot · error · SocketException

Socket is closed

Error message

Socket is closed

What it means

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.

Source

Thrown at buildpack/spring-boot-buildpack-platform/src/main/java/org/springframework/boot/buildpack/platform/socket/UnixDomainSocket.java:59

	 * @throws IOException if the socket cannot be opened
	 */
	public static Socket get(String path) throws IOException {
		return new UnixDomainSocket(path);
	}

	private final SocketAddress socketAddress;

	private final SocketChannel socketChannel;

	private UnixDomainSocket(String path) throws IOException {
		this.socketAddress = UnixDomainSocketAddress.of(path);
		this.socketChannel = SocketChannel.open(this.socketAddress);
	}

	@Override
	public InputStream getInputStream() throws IOException {
		if (isClosed()) {
			throw new SocketException("Socket is closed");
		}
		if (!isConnected()) {
			throw new SocketException("Socket is not connected");
		}
		if (isInputShutdown()) {
			throw new SocketException("Socket input is shutdown");
		}

		return Channels.newInputStream(this.socketChannel);
	}

	@Override
	public OutputStream getOutputStream() throws IOException {
		if (isClosed()) {
			throw new SocketException("Socket is closed");
		}
		if (!isConnected()) {
			throw new SocketException("Socket is not connected");

View on GitHub (pinned to 270dfe353f)

Solutions

  1. Do not use the socket after close(); move all I/O inside the socket's try-with-resources block.
  2. If the socket is pooled, reopen it via UnixDomainSocket.get(path) after eviction.
  3. Audit for double-close or shared references that close out from under a reader.

Example fix

// before
try (Socket s = UnixDomainSocket.get(path)) {
    // ...
}
return s.getInputStream(); // throws "Socket is closed"
// after
try (Socket s = UnixDomainSocket.get(path);
     InputStream in = s.getInputStream()) {
    // read here
}
Defensive patterns

Strategy: validation

Validate before calling

// Guard before obtaining a stream
if (socket.isClosed()) {
    socket = UnixDomainSocket.get(path); // reopen
}
InputStream in = socket.getInputStream();

Try / catch

try {
    socket.getInputStream();
} catch (java.net.SocketException ex) {
    if ("Socket is closed".equals(ex.getMessage())) {
        socket = UnixDomainSocket.get(path); // reopen and retry once
    } else throw ex;
}

Prevention

When it happens

Trigger: getInputStream() or getOutputStream() is called after close() ran — either an explicit close() call or a try-with-resources that exited.

Common situations: 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.

Related errors


AI-assisted analysis of spring-projects/spring-boot@270dfe353f (2026-08-11). Data as JSON: /api/errors/c3cad0e6623e4e5a. Report an issue: GitHub.