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

  1. Investigate the wrapped cause `e` printed with this exception — fix the underlying bind/IO error
  2. Check for port exhaustion: netstat/ss for TIME_WAIT or listening sockets and raise net.ipv4.ip_local_port_range
  3. Reduce concurrency or reuse allocated ports instead of allocating a new port per object
  4. 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

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


AI-assisted analysis of apache/pulsar@820761864e (2026-09-06). Data as JSON: /api/errors/5d92806fd2db25b6. Report an issue: GitHub.