{"record":{"id":"f4e0bec6b4bc42e3","repo":"karatelabs/karate","slug":"could-not-start-callback-server-on-any-configured-port-java","errorCode":null,"errorMessage":"Could not start callback server on any configured port: \" + java.util.Arrays.toString(ports) + \". \" + \"Please ensure at least one port is available, or configure different ports using 'callbackPort' or 'callbackPorts'. \" + \"These ports must be registered as redirect URIs with your OAuth provider.\"","messagePattern":"Could not start callback server on any configured port: \" \\+ java\\.util\\.Arrays\\.toString\\(ports\\) \\+ \"\\. \" \\+ \"Please ensure at least one port is available, or configure different ports using 'callbackPort' or 'callbackPorts'\\. \" \\+ \"These ports must be registered as redirect URIs with your OAuth provider\\.\"","errorType":"exception","errorClass":"OAuth2Exception","httpStatus":null,"severity":"critical","filePath":"karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java","lineNumber":243,"sourceCode":"     * Start callback server on configured or default ports\n     */\n    private String startCallbackServer(LocalCallbackServer server) {\n        int[] ports = getConfiguredPorts();\n\n        Exception lastException = null;\n        for (int port : ports) {\n            try {\n                String redirectUri = server.start(port);\n                logger.debug(\"Callback server started on port {}\", port);\n                return redirectUri;\n            } catch (Exception e) {\n                logger.warn(\"Port {} in use, trying next port\", port);\n                lastException = e;\n            }\n        }\n\n        // If all configured ports fail, provide helpful error message\n        throw new OAuth2Exception(\n            \"Could not start callback server on any configured port: \" + java.util.Arrays.toString(ports) + \". \" +\n            \"Please ensure at least one port is available, or configure different ports using 'callbackPort' or 'callbackPorts'. \" +\n            \"These ports must be registered as redirect URIs with your OAuth provider.\",\n            lastException\n        );\n    }\n\n    /**\n     * Get configured callback ports or use defaults\n     */\n    private int[] getConfiguredPorts() {\n        // Check for single port configuration\n        Object callbackPort = config.get(\"callbackPort\");\n        if (callbackPort != null) {\n            return new int[] { parsePort(callbackPort) };\n        }\n\n        // Check for multiple ports configuration","sourceCodeStart":225,"sourceCodeEnd":261,"githubUrl":"https://github.com/karatelabs/karate/blob/a22eb90246d958d15a47bf436693d0121ad2812d/karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java#L225-L261","documentation":"Thrown by startCallbackServer (reached via redirectUri) when it fails to bind the local HTTP callback server on every configured port. The local loopback server must be listening before the authorization redirect can be received; without it the OAuth code flow cannot complete.","triggerScenarios":"All ports in callbackPort/callbackPorts (or defaults) are already in use by other processes, or the OS refuses to bind (permissions, disabled loopback), so every ServerSocket bind attempt throws and the loop exhausts the port list.","commonSituations":"Another instance of the test/agent still running and holding the port; a dev server occupying the configured callbackPort; Docker/container environments where loopback binding is restricted; stale processes after a crashed previous run.","solutions":["Find and stop the process holding the port (lsof -i :<port> / netstat -ano), or kill the stale previous run.","Configure a different free port via callbackPort, or several via callbackPorts, and register all of them as redirect URIs with your OAuth provider.","Use a privileged high port (>1024) to avoid permission issues, and check container port-binding restrictions if running in Docker."],"exampleFix":"// before\n.callbackPort(8080) // occupied by a dev server\n// after\n.callbackPorts(\"9090,9091,9092\") // free ports, registered with provider\n// and register http://localhost:9090/* etc. as allowed redirect URIs","handlingStrategy":"fallback","validationCode":"// Pre-check that at least one callback port is free before starting the flow\nint[] ports = {9090, 9091, 9092};\nboolean anyFree = false;\nfor (int p : ports) {\n    try (java.net.ServerSocket ss = new java.net.ServerSocket(p)) { anyFree = true; break; }\n    catch (java.io.IOException ignored) {}\n}\nif (!anyFree) throw new IllegalStateException(\"No callback port free: \" + java.util.Arrays.toString(ports));","typeGuard":null,"tryCatchPattern":"try {\n    handler.token();\n} catch (OAuth2Exception e) {\n    if (e.getMessage().startsWith(\"Could not start callback server\")) {\n        // free the ports (kill stale process) or reconfigure callbackPorts and restart\n    }\n}","preventionTips":["Configure multiple callbackPorts and register every one as a redirect URI with the provider.","Kill stale previous test processes that hold the callback port (lsof -i :<port>).","Avoid common dev ports (8080, 3000) for callbacks; prefer ephemeral high ports.","In containers, verify loopback binding is permitted."],"tags":["oauth2","network","port","bind"],"backgroundTag":"address-already-in-use","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"}