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

  1. 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)
  2. Fix the socket list construction so it yields at least one bound socket (e.g. Socket.tcp_server_sockets(port).first or unix server)
  3. If you intended to serve one socket, pass it directly: Socket.accept_loop(server) { |s, addr| ... }
  4. 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

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


AI-assisted analysis of ruby/ruby@0e5b888e1c (2026-08-21). Data as JSON: /api/errors/0e9c0f6866012bb8. Report an issue: GitHub.