karatelabs/karate · critical · OAuth2Exception
Could not start callback server on any configured port: " +…
Error message
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."
What it means
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.
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.
Example fix
// before
.callbackPort(8080) // occupied by a dev server
// after
.callbackPorts("9090,9091,9092") // free ports, registered with provider
// and register http://localhost:9090/* etc. as allowed redirect URIs Defensive patterns
Strategy: fallback
Validate before calling
// Pre-check that at least one callback port is free before starting the flow
int[] ports = {9090, 9091, 9092};
boolean anyFree = false;
for (int p : ports) {
try (java.net.ServerSocket ss = new java.net.ServerSocket(p)) { anyFree = true; break; }
catch (java.io.IOException ignored) {}
}
if (!anyFree) throw new IllegalStateException("No callback port free: " + java.util.Arrays.toString(ports)); Try / catch
try {
handler.token();
} catch (OAuth2Exception e) {
if (e.getMessage().startsWith("Could not start callback server")) {
// free the ports (kill stale process) or reconfigure callbackPorts and restart
}
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- Token endpoint returned invalid response: " +…
- client credentials auth request failed: " + e.getMessage()
- failed to find free port
- Could not start callback server on any configured port…
- port : not available after attempts
AI-assisted analysis of karatelabs/karate@a22eb90246 (2026-09-12).
Data as JSON: /api/errors/f4e0bec6b4bc42e3.
Report an issue: GitHub.
Appendix: source
Thrown at karate-core/src/main/java/io/karatelabs/http/AuthorizationCodeAuthHandler.java:243
* Start callback server on configured or default ports
*/
private String startCallbackServer(LocalCallbackServer server) {
int[] ports = getConfiguredPorts();
Exception lastException = null;
for (int port : ports) {
try {
String redirectUri = server.start(port);
logger.debug("Callback server started on port {}", port);
return redirectUri;
} catch (Exception e) {
logger.warn("Port {} in use, trying next port", port);
lastException = e;
}
}
// If all configured ports fail, provide helpful error message
throw new OAuth2Exception(
"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.",
lastException
);
}
/**
* Get configured callback ports or use defaults
*/
private int[] getConfiguredPorts() {
// Check for single port configuration
Object callbackPort = config.get("callbackPort");
if (callbackPort != null) {
return new int[] { parsePort(callbackPort) };
}
// Check for multiple ports configurationView on GitHub (pinned to a22eb90246)