Skip to content

Errno::EPIPE / Errno::ECONNRESET in accept loop logged as unhandled exceptions #333

@thomaswitt

Description

@thomaswitt

When a client disconnects mid-response (e.g. browser navigation, WebSocket teardown, load-balancer health-check timeout), Falcon::Server#accept raises Errno::EPIPE or Errno::ECONNRESET. These bubble up through the Async task runner and are logged as: "Task may have ended with unhandled exception."

These are expected, harmless disconnects, but they flood logs with false alarms.

Reproduction

  1. Start a Falcon-based Rails app
  2. Use Turbo Drive to navigate between pages quickly (or let an ALB health-check timeout)
  3. Observe console output:
Task may have ended with unhandled exception.
Errno::ECONNRESET: Connection reset by peer

This is particularly noisy with Hotwire/Turbo Drive, where every client-side navigation aborts the
previous response.

Current workaround

We monkey-patch Falcon::Server#accept to swallow only these two specific errors:

class Falcon::Server
  alias_method :__original_accept, :accept

  def accept(...)
    __original_accept(...)
  rescue Errno::EPIPE, Errno::ECONNRESET
    # Client disconnected mid-response — expected.
  end
end

Suggested fix

Handle Errno::EPIPE and Errno::ECONNRESET inside Falcon::Server#accept (or the connection task it spawns). These are not actionable errors — the client is simply gone. Something like:

def accept(...)
  @accept_count += 1
  @connection_count += 1

  super
rescue Errno::EPIPE, Errno::ECONNRESET
  # Client disconnected — nothing to do.
ensure
  @connection_count -= 1
end

All other exceptions would still propagate normally.

Or maybe intrduce a configuration switch whether to warn about these kind of errors

Environment

  • Falcon: 0.54.0
  • async-http: 0.94.2
  • Ruby: 3.4.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions