Feature #21642
Updated by ioquatix (Samuel Williams) 1 day ago
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 ConnectionReset < Errno::ECONNRESET; end class BrokenPipeError BrokenPipe < 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` `IO::ConnectionReset` 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 `IO::ConnectionReset < 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 IO::ConnectionReset puts "Connection was reset by peer." rescue IO::BrokenPipe puts "Connection was broken (EPIPE)." 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.