{"record":{"id":"ee54a2b69c772757","repo":"floci-io/floci","slug":"could-not-find-a-free-port","errorCode":null,"errorMessage":"Could not find a free port","messagePattern":"Could not find a free port","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"error","filePath":"src/main/java/io/github/hectorvent/floci/core/common/docker/PortAllocator.java","lineNumber":79,"sourceCode":"            LOG.debugv(\"Released port {0}\", String.valueOf(port));\n        }\n    }\n\n    /**\n     * Finds any free TCP port using ephemeral port allocation.\n     * This is the fastest method when any port will do.\n     *\n     * @return a free port\n     * @throws RuntimeException if no free port can be allocated\n     */\n    public int allocateAny() {\n        try (ServerSocket socket = new ServerSocket(0)) {\n            socket.setReuseAddress(true);\n            int port = socket.getLocalPort();\n            LOG.debugv(\"Allocated ephemeral port {0}\", String.valueOf(port));\n            return port;\n        } catch (IOException e) {\n            throw new RuntimeException(\"Could not find a free port\", e);\n        }\n    }\n\n    /**\n     * Checks if a specific port is currently free.\n     *\n     * @param port the port to check\n     * @return true if the port is available, false otherwise\n     */\n    public boolean isPortFree(int port) {\n        try (ServerSocket socket = new ServerSocket(port)) {\n            socket.setReuseAddress(true);\n            return true;\n        } catch (IOException e) {\n            return false;\n        }\n    }\n}","sourceCodeStart":61,"sourceCodeEnd":97,"githubUrl":"https://github.com/floci-io/floci/blob/62ff490619e7bd3554597c28c704081b4c15add5/src/main/java/io/github/hectorvent/floci/core/common/docker/PortAllocator.java#L61-L97","documentation":"Thrown by PortAllocator.allocateAny when opening an ephemeral ServerSocket on port 0 fails with an IOException — the OS could not hand out an ephemeral port at all. This is not range exhaustion (no range involved); it means socket creation itself failed, and the original IOException is chained.","triggerScenarios":"File-descriptor exhaustion on the host (ulimit -n reached), unusual security managers or seccomp profiles blocking socket binds, or a heavily loaded host with no ephemeral ports free in the OS range.","commonSituations":"Long-running test suites leaking sockets/fds; containers run with very low fd limits; CI runners under heavy parallel load; SELinux/AppArmor restricting binds.","solutions":["Check the chained exception for the underlying cause (e.g. 'Too many open files')","Raise the process fd limit (ulimit -n 65536) or restart the emulator to release leaked fds","Find and stop whatever is consuming all ephemeral ports or file descriptors (lsof / ss)","Reduce parallelism of container launches in test runs"],"exampleFix":"# before: default limits in CI\n# (fd exhaustion during parallel tests)\n\n# after\nulimit -n 65536\n./mvnw test","handlingStrategy":"fallback","validationCode":"// health check for fd/ephemeral headroom before heavy allocation\nlong openFds = Files.list(Path.of(\"/proc/self/fd\")).count();\nif (openFds > 0.9 * fdLimit()) throw new IllegalStateException(\"fd exhaustion imminent\");","typeGuard":null,"tryCatchPattern":"try {\n    return allocator.allocateAny();\n} catch (RuntimeException e) {\n    // inspect e.getCause(): 'Too many open files' -> raise ulimit / restart; else check policy\n}","preventionTips":["Raise ulimit -n in containers and CI runners","Monitor fd usage on long-running emulator processes","Avoid launching hundreds of containers in parallel from one process"],"tags":["ports","os-limits","fd-exhaustion","docker"],"backgroundTag":null,"analyzedSha":"62ff490619e7bd3554597c28c704081b4c15add5","analyzedAt":"2026-08-14T14:25:23.764Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}