Issue #21642 has been updated by mame (Yusuke Endoh). I talked with @akr-san. He said it should be first confirmed whether you have any real use cases that actually want to handle situations like "can't read but can write" (or vice versa). Pipes are typically unidirectional, so when a write operation throws EPIPE, it means the pipe is write-only, so read operations does not work regardless of EPIPE. TCP sockets have the concept of half-close, but this is difficult to use correctly. If the only action a user can take is "close" in most cases, it would be good to introduce only one module and consider the good name, @akr said. ---------------------------------------- Feature #21642: Introduce `IO::ConnectionResetError` and `IO::BrokenPipeError` as standardized IO-level exceptions. https://bugs.ruby-lang.org/issues/21642#change-114880 * Author: ioquatix (Samuel Williams) * Status: Open ---------------------------------------- Currently, different IO implementations in Ruby raise inconsistent exception types when a connection is reset or broken. For example: ```ruby # Plain TCP socket: socket.read_nonblock(1024) # => Errno::ECONNRESET # SSL socket: ssl_socket.read_nonblock(1024) # => OpenSSL::SSL::SSLError: SSL_read: unexpected eof while reading ``` Both represent a *connection reset by peer*, but the errors differ significantly in type and message. This inconsistency makes it difficult to handle connection-level errors generically across IO types. Similarly, `EPIPE` is used in some contexts to signal a *broken connection*, but again, the representation and message differ between IO classes. ### Proposal Introduce explicit subclasses of the corresponding system errors as part of Ruby’s standard IO interface: ```ruby class IO class ConnectionResetError < Errno::ECONNRESET; end class BrokenPipeError < Errno::EPIPE; end end ``` Then, standardize the Ruby I/O ecosystem (including OpenSSL) to raise these subclasses instead of raw system errors or library-specific error wrappers. This would establish a consistent, well-defined public interface for handling connection-level failures. ### Motivation * **Consistency:** Users can handle `IO::ConnectionResetError` across `IO`, `TCPSocket`, `OpenSSL::SSL::SSLSocket`, and other IO-like objects. * **Clarity:** The name clearly expresses a high-level semantic (“connection reset”) rather than a low-level system error. * **Extensibility:** Other Ruby IO implementations (custom sockets, pipes, etc.) can follow the same convention. * **Backwards Compatibility:** Because `IO::ConnectionResetError < Errno::ECONNRESET`, existing rescue clauses continue to work: ```ruby rescue Errno::ECONNRESET # still catches it end ``` ### Examples ```ruby begin io.read_nonblock(1024) rescue IO::ConnectionResetError puts "Connection was reset by peer." end ``` ### Impact on existing code * Minimal to none. * Existing code that rescues `Errno::ECONNRESET` or `Errno::EPIPE` will continue to function. * Future code gains a more semantic and portable way to handle these common failure modes. -- https://bugs.ruby-lang.org/