pentaho/pentaho-kettle · warning · IOException

Interrupted while waiting to retry callback server startup

Error message

Interrupted while waiting to retry callback server startup

What it means

startCallbackServerWithRetry retries binding the OAuth callback HTTP server while the port is busy, sleeping SERVER_START_RETRY_DELAY_MS between attempts. If Thread.sleep is interrupted during the retry wait, it restores the interrupt flag and throws IOException('Interrupted while waiting to retry callback server startup') with the InterruptedException as cause. authenticate() propagates this to the caller.

Solutions

  1. Treat this as a user-initiated cancellation: detect it via cause instanceof InterruptedException and abort the login flow cleanly.
  2. Free the callback port: kill the stale process listening on the port (or pick another free port) so retries are not needed.
  3. If interruption is not expected, audit who calls Thread.interrupt() on this thread (dialog cancel handlers, executors shut down mid-login).

Example fix

// before
try {
  service.authenticate();
} catch ( IOException e ) {
  throw e;
}
// after
try {
  service.authenticate();
} catch ( IOException e ) {
  if ( e.getCause() instanceof InterruptedException ) {
    Thread.currentThread().interrupt();
    return; // user cancelled login; do not retry
  }
  throw e;
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify the callback port is free before starting authentication
try ( ServerSocket probe = new ServerSocket( callbackPort ) ) {
  // port available
} catch ( IOException busy ) {
  chooseAlternativePort();
}

Try / catch

try {
  authService.authenticate();
} catch ( IOException e ) {
  if ( e.getCause() instanceof InterruptedException ) {
    Thread.currentThread().interrupt();
    LOGGER.info( "Browser authentication cancelled by user" );
  } else {
    throw e;
  }
}

Prevention

When it happens

Trigger: Calling authenticate() when the callback port is occupied for longer than the retry budget, and the waiting thread's interrupt() is invoked (e.g. user cancels the dialog, VM shutdown, or a watchdog cancels the login).

Common situations: User closes the browser-auth window while the callback server is stuck retrying; application shutdown hooks interrupting background login; another process holding the callback port (port conflict from a stale previous instance).

Related errors


AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13). Data as JSON: /api/errors/50383e92f1cc1dad. Report an issue: GitHub.

Appendix: source

Thrown at ui/src/main/java/org/pentaho/di/ui/repo/service/BrowserAuthenticationService.java:202

  void startCallbackServerWithRetry() throws IOException {
    IOException lastException = null;
    for ( int attempt = 1; attempt <= SERVER_START_MAX_RETRIES; attempt++ ) {
      try {
        startCallbackServer();
        return;
      } catch ( IOException e ) {
        lastException = e;
        if ( !isAddressAlreadyInUse( e ) || attempt == SERVER_START_MAX_RETRIES ) {
          throw e;
        }
        log.logBasic( "Callback port still busy; retrying callback server start (attempt "
          + attempt + "/" + SERVER_START_MAX_RETRIES + ")" );
        try {
          Thread.sleep( SERVER_START_RETRY_DELAY_MS );
        } catch ( InterruptedException interrupted ) {
          Thread.currentThread().interrupt();
          throw new IOException( "Interrupted while waiting to retry callback server startup", interrupted );
        }
      }
    }
    if ( lastException != null ) {
      throw lastException;
    }
  }

  boolean isAddressAlreadyInUse( Throwable throwable ) {
    Throwable current = throwable;
    while ( current != null ) {
      if ( current instanceof BindException ) {
        return true;
      }
      String message = current.getMessage();
      if ( message != null && message.toLowerCase( Locale.ROOT ).contains( "address already in use" ) ) {
        return true;
      }

View on GitHub (pinned to f3058517a1)