{"record":{"id":"0e9c0f6866012bb8","repo":"ruby/ruby","slug":"no-sockets","errorCode":null,"errorMessage":"no sockets","messagePattern":"no sockets","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"ext/socket/lib/socket.rb","lineNumber":1258,"sourceCode":"      end\n    else\n      sockets\n    end\n  end\n\n  # yield socket and client address for each a connection accepted via given sockets.\n  #\n  # The arguments are a list of sockets.\n  # The individual argument should be a socket or an array of sockets.\n  #\n  # This method yields the block sequentially.\n  # It means that the next connection is not accepted until the block returns.\n  # So concurrent mechanism, thread for example, should be used to service multiple clients at a time.\n  #\n  def self.accept_loop(*sockets) # :yield: socket, client_addrinfo\n    sockets.flatten!(1)\n    if sockets.empty?\n      raise ArgumentError, \"no sockets\"\n    end\n    loop {\n      readable, _, _ = IO.select(sockets)\n      readable.each {|r|\n        sock, addr = r.accept_nonblock(exception: false)\n        next if sock == :wait_readable\n        yield sock, addr\n      }\n    }\n  end\n\n  # creates a TCP/IP server on _port_ and calls the block for each connection accepted.\n  # The block is called with a socket and a client_address as an Addrinfo object.\n  #\n  # If _host_ is specified, it is used with _port_ to determine the server addresses.\n  #\n  # The socket is *not* closed when the block returns.\n  # So application should close it explicitly.","sourceCodeStart":1240,"sourceCodeEnd":1276,"githubUrl":"https://github.com/ruby/ruby/blob/0e5b888e1c355f3f728f2659f085820937dada48/ext/socket/lib/socket.rb#L1240-L1276","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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"],"exampleFix":"# before\nlisteners = config[:listeners] || []\nSocket.accept_loop(*listeners) { |sock, addr| handle(sock) } # => ArgumentError: no sockets\n\n# after\nlisteners = Socket.tcp_server_sockets(port)\nSocket.accept_loop(listeners) { |sock, addr| handle(sock) }","handlingStrategy":"validation","validationCode":"listeners = listeners.flatten.compact\nabort 'no listening sockets configured' if listeners.empty?\nSocket.accept_loop(*listeners) { |s, a| handle(s, a) }","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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"],"tags":["network","socket","accept-loop","argument-validation"],"backgroundTag":"empty-arguments","analyzedSha":"0e5b888e1c355f3f728f2659f085820937dada48","analyzedAt":"2026-08-21T14:25:43.473Z","schemaVersion":2},"datasetVersion":"2026-08-21T18:17:14.833Z"}