ruby/ruby · error · ArgumentError
no sockets
Error message
no sockets
What it means
ArgumentError raised by Socket.accept_loop (socket.rb:1258) when, after flatten!(1), the argument list contains no sockets. accept_loop multiplexes IO.select over the sockets you pass it, so an empty set is a caller bug and is rejected immediately.
Source
Thrown at ext/socket/lib/socket.rb:1258
end
else
sockets
end
end
# yield socket and client address for each a connection accepted via given sockets.
#
# The arguments are a list of sockets.
# The individual argument should be a socket or an array of sockets.
#
# This method yields the block sequentially.
# It means that the next connection is not accepted until the block returns.
# So concurrent mechanism, thread for example, should be used to service multiple clients at a time.
#
def self.accept_loop(*sockets) # :yield: socket, client_addrinfo
sockets.flatten!(1)
if sockets.empty?
raise ArgumentError, "no sockets"
end
loop {
readable, _, _ = IO.select(sockets)
readable.each {|r|
sock, addr = r.accept_nonblock(exception: false)
next if sock == :wait_readable
yield sock, addr
}
}
end
# creates a TCP/IP server on _port_ and calls the block for each connection accepted.
# The block is called with a socket and a client_address as an Addrinfo object.
#
# If _host_ is specified, it is used with _port_ to determine the server addresses.
#
# The socket is *not* closed when the block returns.
# So application should close it explicitly.View on GitHub (pinned to 0e5b888e1c)
Solutions
- Guard before the call: only enter the accept loop when listeners is non-empty (return/skip with a log line when there is nothing to serve)
- Fix the socket list construction so it yields at least one bound socket (e.g. Socket.tcp_server_sockets(port).first or unix server)
- If you intended to serve one socket, pass it directly: Socket.accept_loop(server) { |s, addr| ... }
- rescue ArgumentError in framework bootstrap code and report the misconfiguration instead of crashing the worker
Example fix
# before
listeners = config[:listeners] || []
Socket.accept_loop(*listeners) { |sock, addr| handle(sock) } # => ArgumentError: no sockets
# after
listeners = Socket.tcp_server_sockets(port)
Socket.accept_loop(listeners) { |sock, addr| handle(sock) } Defensive patterns
Strategy: validation
Validate before calling
listeners = listeners.flatten.compact
abort 'no listening sockets configured' if listeners.empty?
Socket.accept_loop(*listeners) { |s, a| handle(s, a) } Prevention
- Build listener lists from Socket.tcp_server_sockets / UNIXServer constructors that always return sockets
- Fail loudly at config-load time when zero listeners are configured, before reaching the accept loop
- Splat defensively: flatten nested arrays and drop nils before passing them in
When it happens
Trigger: Socket.accept_loop with no arguments; passing only empty arrays such as Socket.accept_loop([]); passing sockets stored in a variable that is nil/empty at runtime (e.g. a server list built from config that produced zero entries); splatting an empty array: Socket.accept_loop(*listeners).
Common situations: Servers built from configurable listeners where config yields none; tests that pass a fixture list which is sometimes empty; refactors that move accept_loop behind a loop-preparation step that can legitimately produce zero sockets.
Related errors
- unbound IPv4 socket
- unbound IPv6 socket
- unbound Unix socket
- Cannot specify open_timeout along with connect_timeout or re
- no appropriate local address
AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21).
Data as JSON: /api/errors/0e9c0f6866012bb8.
Report an issue: GitHub.