Project

General

Profile

Actions

Feature #21642

open

Introduce `IO::ConnectionResetError` and `IO::BrokenPipeError` as standardized IO-level exceptions.

Feature #21642: Introduce `IO::ConnectionResetError` and `IO::BrokenPipeError` as standardized IO-level exceptions.

Added by ioquatix (Samuel Williams) 1 day ago. Updated about 1 hour ago.

Status:
Open
Assignee:
-
Target version:
-
[ruby-core:<unknown>]

Description

Currently, different IO implementations in Ruby raise inconsistent exception types when a connection is reset or broken.

For example:

# 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:

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:

    rescue Errno::ECONNRESET
      # still catches it
    end
    

Examples

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.
Actions

Also available in: PDF Atom