-
-
Notifications
You must be signed in to change notification settings - Fork 95
Description
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
- Start a Falcon-based Rails app
- Use Turbo Drive to navigate between pages quickly (or let an ALB health-check timeout)
- 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