SeleniumHQ/selenium · critical · Error::WebDriverError

unable to bind to locking port #{@port} within #{@timeout} s

Error message

unable to bind to locking port #{@port} within #{@timeout} seconds

What it means

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.

Source

Thrown at rb/lib/selenium/webdriver/common/socket_lock.rb:57

        lock

        begin
          yield
        ensure
          release
        end
      end

      private

      def lock
        max_time = current_time + @timeout

        sleep 0.1 until can_lock? || current_time >= max_time

        return if did_lock?

        raise Error::WebDriverError, "unable to bind to locking port #{@port} within #{@timeout} seconds"
      end

      def current_time
        Process.clock_gettime(Process::CLOCK_MONOTONIC)
      end

      def release
        @server&.close
      end

      def can_lock?
        @server = TCPServer.new(Platform.localhost, @port)
        @server.close_on_exec = true
        true
      rescue SocketError, Errno::EADDRINUSE, Errno::EBADF => e
        WebDriver.logger.debug("#{self}: #{e.message}", id: :driver_service)
        false
      end

View on GitHub (pinned to aa36b38e69)

Solutions

  1. Ensure proper driver.quit / service.stop teardown so no lingering processes hold ports.
  2. Stagger parallel driver initialization to avoid simultaneous port lock contention.
  3. Kill orphaned driver processes: pkill -f chromedriver / pkill -f geckodriver.
  4. Use different base ports for different driver instances if running in parallel.
  5. Check what is holding the port: lsof -i :<port> or ss -tlnp | grep <port>.

Example fix

// before
# parallel tests all start at once, contending on same port-1 lock
threads = 10.times.map do
  Thread.new { Selenium::WebDriver.for :chrome }
end

// after (stagger + explicit teardown)
drivers = []
10.times.each do |i|
  service = Selenium::WebDriver::Service.chrome(port: 9515 + i * 10)
  drivers << Selenium::WebDriver.for(:chrome, service: service)
  sleep 0.5
end
# always quit
at_exit { drivers.each(&:quit) }
Defensive patterns

Strategy: retry

Validate before calling

# Ensure no orphaned driver processes before starting
system('pkill -f chromedriver 2>/dev/null') if ENV['CLEANUP_DRIVERS']
system('pkill -f geckodriver 2>/dev/null')

# Use distinct ports per parallel worker
base_port = 9515 + (ENV.fetch('TEST_ENV_NUMBER', 1).to_i * 10)
service = Selenium::WebDriver::Service.chrome(port: base_port)

Try / catch

begin
  driver = Selenium::WebDriver.for(:chrome, service: service)
rescue Selenium::WebDriver::Error::WebDriverError => e
  raise unless e.message.include?('unable to bind to locking port')
  # port contention; retry with a different base port
  service = Selenium::WebDriver::Service.chrome(port: rand(20000..30000))
  driver = Selenium::WebDriver.for(:chrome, service: service)
end

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Understand the failure class

Related errors


AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14). Data as JSON: /api/errors/8af3a27695dad593. Report an issue: GitHub.