karatelabs/karate · warning

port : not available after attempts

Error message

port {}:{} not available after {} attempts

What it means

`PortUtils.waitForPort` exhausted all attempts without a successful TCP connection to host:port. It logs this warning and returns false, meaning the service never became reachable within the configured attempt budget.

Solutions

  1. Confirm the service actually started and which port/interface it bound (logs, `netstat`/`ss`)
  2. Increase `attempts` or `intervalMs` to cover slow startup
  3. Verify host is correct (localhost vs container hostname vs external IP)
  4. Check firewall/security-group rules blocking the port

Example fix

// before
boolean up = PortUtils.waitForPort("localhost", 8080, 10, 200, alive);
// after
boolean up = PortUtils.waitForPort("localhost", 8080, 60, 500, alive);
Defensive patterns

Strategy: retry

Try / catch

if (!PortUtils.waitForPort(host, port, 60, 500, alive)) {
    throw new RuntimeException("port " + host + ":" + port + " never opened; check service logs");
}

Prevention

When it happens

Trigger: `waitForPort('localhost', 8080, 30, 500, stillAlive)` where nothing listens on 8080; server started but bound to a different port/interface (e.g. 127.0.0.1 vs container IP); attempts/interval too small for a slow-starting service.

Common situations: Firewall or network policy blocking the port; service binding only to a specific interface; docker port mapping mistakes; under-provisioned timeout for slow JVM/framework startup in CI.

Understand the failure class

Background: ECONNREFUSED and "connection refused" / "could not connect to server" errors: what they mean and how to fix them — this error's family across 44 libraries.

Related errors


AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12). Data as JSON: /api/errors/15a8e999471a0ee0. Report an issue: GitHub.

Appendix: source

Thrown at karate-core/src/main/java/io/karatelabs/process/PortUtils.java:74

     * @param stillAlive Supplier that returns false if we should stop waiting (e.g., process died)
     * @return true if port is available, false if timed out or process died
     */
    public static boolean waitForPort(String host, int port, int attempts, int intervalMs, BooleanSupplier stillAlive) {
        for (int i = 0; i < attempts; i++) {
            if (stillAlive != null && !stillAlive.getAsBoolean()) {
                logger.warn("process died while waiting for port {}:{}", host, port);
                return false;
            }
            try (Socket socket = new Socket()) {
                socket.connect(new InetSocketAddress(host, port), 1000);
                logger.debug("port {}:{} is available after {} attempts", host, port, i + 1);
                return true;
            } catch (Exception e) {
                logger.trace("port {}:{} not yet available (attempt {})", host, port, i + 1);
                sleep(intervalMs);
            }
        }
        logger.warn("port {}:{} not available after {} attempts", host, port, attempts);
        return false;
    }

    /**
     * Wait for an HTTP endpoint to return 200.
     */
    public static boolean waitForHttp(String url, int attempts, int intervalMs, BooleanSupplier stillAlive) {
        HttpClient client = HttpClient.newBuilder()
                .connectTimeout(Duration.ofSeconds(5))
                .build();
        for (int i = 0; i < attempts; i++) {
            if (stillAlive != null && !stillAlive.getAsBoolean()) {
                logger.warn("process died while waiting for HTTP {}", url);
                return false;
            }
            try {
                HttpRequest request = HttpRequest.newBuilder()
                        .uri(URI.create(url))

View on GitHub (pinned to a22eb90246)