{"record":{"id":"a29b9743a70d4fcd","repo":"pentaho/pentaho-kettle","slug":"user-canceled-repository-reconnection-after-session-timeout","errorCode":null,"errorMessage":"User canceled repository reconnection after session timeout","messagePattern":"User canceled repository reconnection after session timeout","errorType":"exception","errorClass":"KettleRepositoryLostException","httpStatus":null,"severity":"warning","filePath":"plugins/repositories/core/src/main/java/org/pentaho/di/ui/repo/timeout/SessionTimeoutHandler.java","lineNumber":218,"sourceCode":"   * {@link KettleRepositoryLostException} to stop the current operation.\n   */\n  private void handleLoginCanceled() throws KettleRepositoryLostException {\n    log.logBasic( \"User canceled reconnection after session expiry - disconnecting repository\" );\n    try {\n      Spoon spoon = getSpoon();\n      if ( spoon != null ) {\n        spoon.getDisplay().syncExec( () -> {\n          try {\n            spoon.closeRepository();\n          } catch ( Exception ex ) {\n            log.logError( \"Error closing repository after user canceled reconnection\", ex );\n          }\n        } );\n      }\n    } catch ( Exception e ) {\n      log.logError( \"Error during repository disconnect after cancel\", e );\n    }\n    throw new KettleRepositoryLostException( \"User canceled repository reconnection after session timeout\" );\n  }\n\n\n\n  boolean lookupForConnectTimeoutError( Throwable root ) {\n    while ( root != null ) {\n      if ( EXCEPTION_CLASS_NAME.equals( root.getClass().getSimpleName() ) ) {\n        String errorMessage = root.getMessage();\n        if ( errorMessage.contains( RepositoryConnectController.ERROR_401 ) ) {\n          return true;\n        } else {\n          return false;\n        }\n      } else {\n        root = root.getCause();\n      }\n    }\n    return false;","sourceCodeStart":200,"sourceCodeEnd":236,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/plugins/repositories/core/src/main/java/org/pentaho/di/ui/repo/timeout/SessionTimeoutHandler.java#L200-L236","documentation":"SessionTimeoutHandler.handleLoginCanceled is invoked when the user cancels the re-login dialog during session recovery. It disconnects the repository (ignoring disconnect errors) and throws KettleRepositoryLostException('User canceled repository reconnection after session timeout'). The repository connection is lost and the original operation cannot complete.","triggerScenarios":"Session timeout dialog shown to the user; user clicks Cancel/close; handler disconnects the repository and throws KettleRepositoryLostException up through performLoginAndReinvoke.","commonSituations":"User away from the machine when the timeout dialog appears; user intentionally declines re-login; dialog dismissed accidentally during a long-running transformation.","solutions":["Reconnect to the repository via the Connect dialog and repeat the operation","Save unsaved work before closing, since the repository is disconnected after cancel","Increase the server session timeout so the dialog appears less often","Handle KettleRepositoryLostException in automation/embedded scenarios to prompt reconnection programmatically"],"exampleFix":"// before\nrepository.loadData(...); // aborts with KettleRepositoryLostException if user cancels re-login\n// after\ntry {\n  repository.loadData(...);\n} catch ( KettleRepositoryLostException e ) {\n  spoon.promptRepositoryConnect(); // offer manual reconnect before proceeding\n}","handlingStrategy":"fallback","validationCode":"// detect the cancel path before losing work\nboolean isUserCanceledReconnect( Throwable t ) {\n  while ( t != null ) {\n    if ( t instanceof KettleRepositoryLostException\n         && t.getMessage() != null\n         && t.getMessage().contains( \"canceled\" ) ) return true;\n    t = t.getCause();\n  }\n  return false;\n}","typeGuard":null,"tryCatchPattern":"try {\n  handler.performLoginAndReinvoke( objectToHandle, method, args );\n} catch ( KettleRepositoryLostException e ) {\n  // user canceled: save work locally, then offer manual reconnect\n  saveWorkLocally();\n  spoon.promptRepositoryConnect();\n}","preventionTips":["Save work frequently so a canceled recovery does not lose changes","Increase server session timeout to make the dialog rare","For automation, avoid interactive timeout handlers; use non-blocking reconnect logic","Clearly label the recovery dialog so users know canceling disconnects the repository"],"tags":["session","timeout","user-canceled","repository"],"backgroundTag":"session-expired","analyzedSha":"f3058517a153da500bf4551f46d79b91bf8ec552","analyzedAt":"2026-09-13T14:04:16.340Z","contentChangedAt":"2026-09-13T14:04:16.340Z","schemaVersion":2},"datasetVersion":"2026-09-20T23:17:15.980Z"}