{"record":{"id":"9395bf326d0e2dea","repo":"karatelabs/karate","slug":"http-not-available-after-attempts","errorCode":null,"errorMessage":"HTTP {} not available after {} attempts","messagePattern":"HTTP (.+?) not available after (.+?) attempts","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"karate-core/src/main/java/io/karatelabs/process/PortUtils.java","lineNumber":107,"sourceCode":"            }\n            try {\n                HttpRequest request = HttpRequest.newBuilder()\n                        .uri(URI.create(url))\n                        .timeout(Duration.ofSeconds(5))\n                        .GET()\n                        .build();\n                HttpResponse<String> response = client.send(request, HttpResponse.BodyHandlers.ofString());\n                if (response.statusCode() >= 200 && response.statusCode() < 300) {\n                    logger.debug(\"HTTP {} is available after {} attempts\", url, i + 1);\n                    return true;\n                }\n                logger.trace(\"HTTP {} returned {} (attempt {})\", url, response.statusCode(), i + 1);\n            } catch (Exception e) {\n                logger.trace(\"HTTP {} not available (attempt {}): {}\", url, i + 1, e.getMessage());\n            }\n            sleep(intervalMs);\n        }\n        logger.warn(\"HTTP {} not available after {} attempts\", url, attempts);\n        return false;\n    }\n\n    /**\n     * Find a free port.\n     */\n    public static int findFreePort() {\n        try (ServerSocket socket = new ServerSocket(0)) {\n            return socket.getLocalPort();\n        } catch (Exception e) {\n            throw new RuntimeException(\"failed to find free port\", e);\n        }\n    }\n\n    private static void sleep(int millis) {\n        try {\n            Thread.sleep(millis);\n        } catch (InterruptedException e) {","sourceCodeStart":89,"sourceCodeEnd":125,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/process/PortUtils.java#L89-L125","documentation":"`PortUtils.waitForHttp` completed all attempts without receiving a successful (expected) HTTP response from the URL. It logs this warning and returns false, indicating the endpoint never returned 200 within the budget.","triggerScenarios":"`waitForHttp('http://localhost:8080/health', 20, 500, alive)` where the endpoint returns 500/404 or connection fails each time; app slow to start so every probe hits a non-200; wrong health path.","commonSituations":"Health endpoint path changed or misconfigured; app returning 503 during long warm-up; TLS/proxy issues causing connection errors; readiness depends on downstream services that are also down.","solutions":["Verify the health endpoint URL and path return 200 (curl it manually)","Increase `attempts`/`intervalMs` to accommodate warm-up time","Check the app logs for what it returns on the probe path","Ensure downstream dependencies the health check requires are available"],"exampleFix":"// before\nboolean ok = PortUtils.waitForHttp(\"http://localhost:8080/status\", 10, 250, alive);\n// after\nboolean ok = PortUtils.waitForHttp(\"http://localhost:8080/actuator/health\", 60, 500, alive);","handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"if (!PortUtils.waitForHttp(url, 60, 500, alive)) {\n    throw new RuntimeException(\"HTTP \" + url + \" never returned 200; inspect server logs\");\n}","preventionTips":["Point at a stable, fast health endpoint","Allow extra attempts for warm-up and dependency readiness","Verify the path/port against the server's actual configuration"],"tags":["http","health-check","timeout","network"],"backgroundTag":"http-non-200-response","analyzedSha":"a22eb90246d958d15a47bf436693d0121ad2812d","analyzedAt":"2026-09-12T09:01:00.220Z","contentChangedAt":"2026-09-12T09:01:00.220Z","schemaVersion":2},"datasetVersion":"2026-09-16T19:17:19.609Z"}