pentaho/pentaho-kettle · error · SessionAuthenticationException

Unable to obtain authentication context for URL:

Error message

Unable to obtain authentication context for URL: 

What it means

RepositoryCleanupUtil.authenticateLoginCredentials(), when useSessionAuth is enabled, asks SpoonSessionManager.getInstance().getAuthenticationContext(url) for the current session's AuthenticationContext; if it returns null the method throws SessionAuthenticationException "Unable to obtain authentication context for URL: ...". It means the Spoon session holds no authentication context registered for that exact URL, so login credentials cannot be validated/used for the purge repository call.

Solutions

  1. Log into the repository/server from the Spoon UI so an AuthenticationContext is registered, then retry the purge.
  2. Make the URL string exactly match the one used at login (same scheme, host, port, path).
  3. Switch to basic authentication (useSessionAuth=false) if a headless/scripted run has no Spoon session.
  4. Re-authenticate if the session expired, and normalize/validate the URL before calling the method.

Example fix

// before
util.authenticateLoginCredentials( "http://localhost:8080/pentaho" ); // registered as https://server:8443
// after: reuse the exact registered URL
String url = SpoonSessionManager.getInstance().getActiveRepositoryUrl();
util.authenticateLoginCredentials( url );
Defensive patterns

Strategy: validation

Validate before calling

AuthenticationContext ctx = SpoonSessionManager.getInstance().getAuthenticationContext( url );
if ( ctx == null || !ctx.isAuthenticated() ) { throw new IllegalStateException( "Log into Spoon for URL before purging: " + url ); }

Try / catch

try { util.authenticateLoginCredentials( url ); } catch ( SessionAuthenticationException e ) { /* prompt re-login or fall back to basic auth */ }

Prevention

When it happens

Trigger: authenticateLoginCredentials() invoked with useSessionAuth=true and a URL for which getAuthenticationContext(url) returns null: never logged in from Spoon for that server, the URL string differs (scheme/host/port/trailing slash) from the one registered at login, or the session context expired/was cleared.

Common situations: Running a purge against a URL slightly different from the one used to log in (http vs https, hostname vs IP, port mismatch); attempting purge before logging into the repository through the Spoon UI; session invalidated after idle timeout; testing session auth in headless/scripted environments where no Spoon session exists.

Understand the failure class

Related errors


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

Appendix: source

Thrown at plugins/pur/core/src/main/java/com/pentaho/di/purge/RepositoryCleanupUtil.java:373

  @VisibleForTesting
  void authenticateLoginCredentials() throws Exception {
    KettleClientEnvironment.init();

    if ( client == null ) {
      ClientConfig clientConfig = new ClientConfig();
      clientConfig.property( ClientProperties.FOLLOW_REDIRECTS, Boolean.TRUE );
      client = ClientBuilder.newClient( clientConfig );
      
      // Check if session-based authentication is enabled
      final boolean useSessionAuth = AuthenticationContext.SESSION_AUTH_TOKEN.equals( password );

      if ( useSessionAuth ) {
        // Get authentication context using the factory pattern
        AuthenticationContext authContext =
          SpoonSessionManager.getInstance().getAuthenticationContext( url );

        if ( authContext == null ) {
          throw new SessionAuthenticationException(
            "Unable to obtain authentication context for URL: " + url
              + ". Verify the URL is valid and properly formatted." );
        }

        // Check if authenticated
        if ( authContext.isAuthenticated() ) {
          String jsessionId = authContext.getJSessionId();

          // Register a ClientRequestFilter to add Cookie header to every request
          final String finalJsessionId = jsessionId;
          client.register( (jakarta.ws.rs.client.ClientRequestFilter) requestContext ->
            requestContext.getHeaders().add( "Cookie", "JSESSIONID=" + finalJsessionId )
          );
        } else {
          throw new SessionAuthenticationException( "Session-based authentication is enabled but no valid session found. Please authenticate through browser first." );
        }
      } else {
        // Use basic authentication with username/password

View on GitHub (pinned to f3058517a1)