This error message...
java.lang.RuntimeException: Unable to find a free port
...is a RuntimeException which is the superclass of those exceptions that can be thrown during the normal operation of the Java Virtual Machine.
Protecting the ports that chromedriver use
There is nothing much we can do about the port usage as @barancev mentions ChromeDriver attempts to find a free Ephemeral port using a system-dependent ephemeral port range detector. An ephemeral port is a short-lived endpoint that is created by the operating system when a program requests any available user port. The operating system selects the port number from a predefined range, typically between 1024 and 65535, and releases the port after the related TCP connection terminates.
By default, the system can create a maximum of approximately 4,000 ephemeral ports that run concurrently on Windows Server 2003 and approximately 16,000 on Windows Server 2008.
You can find a detailed discussion in How do I protect the ports that chromedriver use?
Issue in details
As per @visionscaper's comment on Windows systems you need to remove / comment out the following type of entries from C:\Windows\System32\Drivers\etc\hosts
file:
127.0.0.1 my-site.local
192.168.100.48 localhost
As per @DavidGDD's comment on Linux systems in PortProber.java
and LinuxEphemeralPortRangeDetector.java
there is a case in createAcceptablePort
in which is always returning the same port, not random.
- When you have defined in the
/proc/sys/net/ipv4/ip_local_port_range
the port range as 1024-65535
, the method always returns 1024.
- When you change your range defined in the file to
1025-65535
(or any other range) it will work returning random ports.
- @tflori mentions from Selenium point of view:
- LinuxEphemeralPortRangeDetector.java had more than one space between the two ports. So the result was
[1025, , , , 65535]
then Integer.parseInt(split[1]);
throws and the default is used which leads to the same issue we had without modifying the lower port.
- PortProber.java we were geting the highest and lowest ports from the platform and then we overwrite one or the other 1024 or 65535.
Solution
This merge solves the port negotiation problem on linux and other platforms. The removed code leads to the result that FIRST_PORT and LAST_PORT is both set to 1024 which always returns 1024. In fact we should trust the ephemeral ports reports by the detector. With the min and max we just assure a valid port range. So you need to ensure that:
- JDK is upgraded to current levels JDK 8u222.
- Selenium is upgraded to current levels Version 3.141.59.
- ChromeDriver is updated to current ChromeDriver v77.0 level.
- Chrome is updated to current Chrome Version 77.0 level. (as per ChromeDriver v77.0 release notes)
- Clean your Project Workspace through your IDE and Rebuild your project with required dependencies only.
- If your base Web Client version is too old, then uninstall it and install a recent GA and released version of Web Client.
- Take a System Reboot.
- Execute your
@Test
as non-root user.
- Always invoke
driver.quit()
within tearDown(){}
method to close & destroy the WebDriver and Web Client instances gracefully.