{"record":{"id":"8af3a27695dad593","repo":"SeleniumHQ/selenium","slug":"unable-to-bind-to-locking-port-port-within","errorCode":null,"errorMessage":"unable to bind to locking port #{@port} within #{@timeout} seconds","messagePattern":"unable to bind to locking port #(.+?) within #(.+?) seconds","errorType":"exception","errorClass":"Error::WebDriverError","httpStatus":null,"severity":"critical","filePath":"rb/lib/selenium/webdriver/common/socket_lock.rb","lineNumber":57,"sourceCode":"        lock\n\n        begin\n          yield\n        ensure\n          release\n        end\n      end\n\n      private\n\n      def lock\n        max_time = current_time + @timeout\n\n        sleep 0.1 until can_lock? || current_time >= max_time\n\n        return if did_lock?\n\n        raise Error::WebDriverError, \"unable to bind to locking port #{@port} within #{@timeout} seconds\"\n      end\n\n      def current_time\n        Process.clock_gettime(Process::CLOCK_MONOTONIC)\n      end\n\n      def release\n        @server&.close\n      end\n\n      def can_lock?\n        @server = TCPServer.new(Platform.localhost, @port)\n        @server.close_on_exec = true\n        true\n      rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => e\n        WebDriver.logger.debug(\"#{self}: #{e.message}\", id: :driver_service)\n        false\n      end","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/SeleniumHQ/selenium/blob/aa36b38e696a0909e973bdf5e2f9031ffe842c4b/rb/lib/selenium/webdriver/common/socket_lock.rb#L39-L75","documentation":"Raised by SocketLock#lock when the lock cannot be acquired on the port (config.port - 1) within SOCKET_LOCK_TIMEOUT (45 seconds). SocketLock uses a TCP server bind on port-1 as a mutex to prevent concurrent driver instances from racing on the same port range. If that port-1 is continuously occupied (by another process or another driver instance), the lock acquisition times out.","triggerScenarios":"Multiple WebDriver instances trying to start simultaneously on overlapping port ranges. A previous driver process died but left a zombie holding the port. Another application (not Selenium) is bound to the port-1 address. Rapidly starting/stopping many driver instances in parallel tests without proper teardown. Port exhaustion on the system.","commonSituations":"Parallel test suites (RSpec parallel, fork-based) all initializing drivers at once. A crashed test that didn't clean up its driver server process. Another service (database, dev server) coincidentally using ports near the driver's configured port. Running on systems with limited ephemeral port range.","solutions":["Ensure proper driver.quit / service.stop teardown so no lingering processes hold ports.","Stagger parallel driver initialization to avoid simultaneous port lock contention.","Kill orphaned driver processes: pkill -f chromedriver / pkill -f geckodriver.","Use different base ports for different driver instances if running in parallel.","Check what is holding the port: lsof -i :<port> or ss -tlnp | grep <port>."],"exampleFix":"// before\n# parallel tests all start at once, contending on same port-1 lock\nthreads = 10.times.map do\n  Thread.new { Selenium::WebDriver.for :chrome }\nend\n\n// after (stagger + explicit teardown)\ndrivers = []\n10.times.each do |i|\n  service = Selenium::WebDriver::Service.chrome(port: 9515 + i * 10)\n  drivers << Selenium::WebDriver.for(:chrome, service: service)\n  sleep 0.5\nend\n# always quit\nat_exit { drivers.each(&:quit) }","handlingStrategy":"retry","validationCode":"# Ensure no orphaned driver processes before starting\nsystem('pkill -f chromedriver 2>/dev/null') if ENV['CLEANUP_DRIVERS']\nsystem('pkill -f geckodriver 2>/dev/null')\n\n# Use distinct ports per parallel worker\nbase_port = 9515 + (ENV.fetch('TEST_ENV_NUMBER', 1).to_i * 10)\nservice = Selenium::WebDriver::Service.chrome(port: base_port)","typeGuard":null,"tryCatchPattern":"begin\n  driver = Selenium::WebDriver.for(:chrome, service: service)\nrescue Selenium::WebDriver::Error::WebDriverError => e\n  raise unless e.message.include?('unable to bind to locking port')\n  # port contention; retry with a different base port\n  service = Selenium::WebDriver::Service.chrome(port: rand(20000..30000))\n  driver = Selenium::WebDriver.for(:chrome, service: service)\nend","preventionTips":["Always call driver.quit in an ensure block or at_exit to prevent orphaned processes.","In parallel test suites, assign non-overlapping port ranges per worker.","Add a cleanup step at the start of CI to kill orphaned driver processes.","Avoid starting more simultaneous drivers than available system ports."],"tags":["socket-lock","port-contention","parallel","timeout","ruby"],"backgroundTag":null,"analyzedSha":"aa36b38e696a0909e973bdf5e2f9031ffe842c4b","analyzedAt":"2026-08-14T02:32:32.244Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}