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
endView on GitHub (pinned to aa36b38e69)
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>.
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
- 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.
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
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- remote server not ready in {} seconds
- remote server not stopped in #{@timeout} seconds
- -> #{@pid} still alive after #{timeout} seconds
- unable to connect to #{@executable_path} #{@host}:#{@port}:
- timed out after #{@timeout} seconds
AI-assisted analysis of SeleniumHQ/selenium@aa36b38e69 (2026-08-14).
Data as JSON: /api/errors/8af3a27695dad593.
Report an issue: GitHub.