pentaho/pentaho-kettle · error · SessionAuthenticationException
Session-based authentication is enabled but no valid…
Error message
Session-based authentication is enabled but no valid session found. Please authenticate through browser first.
What it means
This error is thrown by RepositoryCleanupUtil.authenticateLoginCredentials when session-based authentication is enabled for the purge client but no valid JSESSIONID browser session is available. Instead of registering a basic-auth HttpAuthenticationFeature, the utility registers a ClientRequestFilter that adds a 'Cookie: JSESSIONID=<jsessionId>' header to every request; when jsessionId is null/blank it refuses to proceed and throws SessionAuthenticationException.
Solutions
- Log into the Pentaho web console in a browser first to obtain a valid JSESSIONID, then re-run with session auth enabled
- Switch to basic authentication mode so HttpAuthenticationFeature.basic(username, decryptedPassword) is registered instead of requiring a session cookie
- Verify the jsessionId configuration/property is populated and current (not an expired session)
- For headless automation, configure basic auth credentials or capture a fresh JSESSIONID programmatically before invoking purge
Example fix
// before: session auth with missing cookie
throw new SessionAuthenticationException( "Session-based authentication is enabled but no valid session found..." );
// after: fall back to basic auth when no session is present
if ( sessionAuthEnabled && jsessionId != null && !jsessionId.isBlank() ) {
client.register( (jakarta.ws.rs.client.ClientRequestFilter) ctx -> ctx.getHeaders().add( "Cookie", "JSESSIONID=" + jsessionId ) );
} else if ( username != null && password != null ) {
client.register( HttpAuthenticationFeature.basic( username, Encr.decryptPasswordOptionallyEncrypted( password ) ) );
} else {
throw new SessionAuthenticationException( "..." );
} Defensive patterns
Strategy: validation
Validate before calling
if ( sessionAuthEnabled && ( jsessionId == null || jsessionId.isBlank() ) ) {
throw new IllegalStateException( "Session auth enabled but no JSESSIONID; log into the Pentaho console first or configure basic auth." );
} Type guard
boolean hasValidSession( String jsessionId ) { return jsessionId != null && !jsessionId.isBlank(); } Try / catch
try {
purgeUtil.authenticateLoginCredentials( client, username, password, useSessionAuth, jsessionId );
} catch ( SessionAuthenticationException e ) {
log.error( "No valid browser session; falling back to basic auth or prompting login", e );
registerBasicAuthOrPrompt();
} Prevention
- Log into the Pentaho web console before running session-auth purges
- Prefer basic auth for headless/CI runs where no browser session exists
- Refresh JSESSIONID whenever the server session times out
- Validate the jsessionId config value non-empty before invoking purge
When it happens
Trigger: Calling purge(), authenticateLoginCredentials(), or the test wrappers when session authentication mode is enabled and the resolved jsessionId is null or empty, so the else branch at line 388 throws SessionAuthenticationException.
Common situations: Running the purge utility against a Pentaho repository where session auth was selected but the user never logged into the Pentaho web console (no browser session cookie captured); an expired JSESSIONID supplied via configuration; automated/headless runs with no interactive browser login available.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- Attempting to create PDI Repository with no Active…
- Browser session authentication requested but no JSESSIONID…
- Unable to obtain authentication context for URL:
- Auth error
- CmsTokenProvider: Keycloak token request failed — HTTP
AI-assisted analysis of pentaho/pentaho-kettle@f3058517a1 (2026-09-13).
Data as JSON: /api/errors/06d4c02b2f88f707.
Report an issue: GitHub.
Appendix: source
Thrown at plugins/pur/core/src/main/java/com/pentaho/di/purge/RepositoryCleanupUtil.java:388
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
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic( username, Encr.decryptPasswordOptionallyEncrypted( password ) );
client.register( feature );
}
}
WebTarget target = client.target( url + AUTHENTICATION + AdministerSecurityAction.NAME );
String response = target.request( MediaType.TEXT_PLAIN ).get( String.class );
if ( !response.equals( "true" ) ) {
throw new Exception( Messages.getInstance().getString( "REPOSITORY_CLEANUP_UTIL.ERROR_0012.ACCESS_DENIED" ) );
}
}
/**
* Create URL to access REST API based on provided parametersView on GitHub (pinned to f3058517a1)