apache/pulsar · error · RuntimeException
Unable to allocate socket port
Error message
Unable to allocate socket port
What it means
PortManager is a test/admin utility that hands out free TCP ports by probing sockets. It tries up to 100 times to bind a candidate port; if every attempt throws (e.g. bind failures), it aborts with this RuntimeException wrapping the last cause. It means the JVM could not find or allocate any usable socket port after repeated attempts.
Source
Thrown at pulsar-common/src/main/java/org/apache/pulsar/common/util/PortManager.java:50
private static final Set<Integer> PORTS = new HashSet<>();
/**
* Return a free port that is reserved for the caller until {@link #releaseLockedPort(int)}
* is invoked.
*/
public static synchronized int nextLockedFreePort() {
int exceptionCount = 0;
while (true) {
try (ServerSocket ss = new ServerSocket(0)) {
int port = ss.getLocalPort();
if (!checkPortIfLocked(port)) {
PORTS.add(port);
return port;
}
} catch (Exception e) {
exceptionCount++;
if (exceptionCount > 100) {
throw new RuntimeException("Unable to allocate socket port", e);
}
}
}
}
/**
* Release a previously locked port.
*
* @return true if the port was previously locked by this manager
*/
public static synchronized boolean releaseLockedPort(int lockedPort) {
return PORTS.remove(lockedPort);
}
/**
* @return true if the port is currently locked by this manager
*/
public static synchronized boolean checkPortIfLocked(int lockedPort) {View on GitHub (pinned to 820761864e)
Solutions
- Investigate the wrapped cause `e` printed with this exception — fix the underlying bind/IO error
- Check for port exhaustion: netstat/ss for TIME_WAIT or listening sockets and raise net.ipv4.ip_local_port_range
- Reduce concurrency or reuse allocated ports instead of allocating a new port per object
- Restart the host or container to clear leaked/ephemeral ports
Example fix
// before: allocating a fresh port per test method int port = PortManager.nextLockedFreePort(); // throws after 100 failures // after: reuse the locked port across the suite private static final AutoCloseable LOCK = PortManager.acquireLock(); int port = PortManager.nextLockedFreePort();
Defensive patterns
Strategy: retry
Validate before calling
// check port availability before relying on PortManager
try (java.net.ServerSocket s = new java.net.ServerSocket()) {
s.bind(new java.net.InetSocketAddress(0));
} catch (java.io.IOException e) {
throw new IllegalStateException("No bindable ports available: " + e.getMessage());
} Try / catch
try {
int port = PortManager.nextLockedFreePort();
} catch (RuntimeException e) {
if (e.getMessage().contains("Unable to allocate socket port")) {
// fall back to ephemeral port (0) or abort with diagnostics
}
} Prevention
- Bind to port 0 (ephemeral) when a fixed allocated port is not required
- Monitor TIME_WAIT/socket counts in CI hosts running parallel test suites
- Raise net.ipv4.ip_local_port_range on test machines/containers
- Reuse one locked port per test class instead of per test method
When it happens
Trigger: Calling nextLockedFreePort() in a tight loop so that more than 100 consecutive attempts to open a candidate port throw; port exhaustion by other processes; restrictive firewall/OS bind restrictions.
Common situations: Test suites that run many brokers/clients concurrently and exhaust the ephemeral port range; running in a container with a narrow net.ipv4.ip_local_port_range; leaked sockets from previous tests holding ports in TIME_WAIT.
Related errors
- Failed to update clusters because failed to create admin cli
- Failed to resolve localhost name.
- Unable to obtain an access token: ${message}
- Unable to retrieve OAuth 2.0 server metadata
- Cannot obtain authorization metadata from ${metadataUrl}
AI-assisted analysis of apache/pulsar@820761864e (2026-09-06).
Data as JSON: /api/errors/5d92806fd2db25b6.
Report an issue: GitHub.