{"record":{"id":"349feef48e86c2ad","repo":"pentaho/pentaho-kettle","slug":"waiting-for-transformation-to-be-finished-interrupted","errorCode":null,"errorMessage":"Waiting for transformation to be finished interrupted!","messagePattern":"Waiting for transformation to be finished interrupted!","errorType":"exception","errorClass":"RuntimeException","httpStatus":null,"severity":"warning","filePath":"engine/src/main/java/org/pentaho/di/trans/Trans.java","lineNumber":1809,"sourceCode":"  /**\n   * Waits until all RunThreads have finished.\n   */\n  public void waitUntilFinished() {\n    try {\n      if ( transFinishedBlockingQueue == null ) {\n        return;\n      }\n      boolean wait = true;\n      while ( wait ) {\n        wait = transFinishedBlockingQueue.poll( 1, TimeUnit.DAYS ) == null;\n        if ( wait ) {\n          // poll returns immediately - this was hammering the CPU with poll checks. Added\n          // a sleep to let the CPU breathe\n          Thread.sleep( 1 );\n        }\n      }\n    } catch ( InterruptedException e ) {\n      throw new RuntimeException( \"Waiting for transformation to be finished interrupted!\", e );\n    }\n  }\n\n  /**\n   * Gets the number of errors that have occurred during execution of the transformation.\n   *\n   * @return the number of errors\n   */\n  public int getErrors() {\n    int nrErrors = errors.get();\n\n    if ( steps == null ) {\n      return nrErrors;\n    }\n\n    for ( int i = 0; i < steps.size(); i++ ) {\n      StepMetaDataCombi sid = steps.get( i );\n      if ( sid.step.getErrors() != 0L ) {","sourceCodeStart":1791,"sourceCodeEnd":1827,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/trans/Trans.java#L1791-L1827","documentation":"Code that waits for a transformation to finish (e.g. waitUntilFinished) polls the running flag in a loop with Thread.sleep(1). If the waiting thread is interrupted (Thread.interrupt()), the InterruptedException is rethrown as a RuntimeException with this message. It indicates the waiter was interrupted, not that the transformation failed.","triggerScenarios":"Calling trans.waitUntilFinished() (or similar polling wait) from a thread that gets interrupted - e.g. executor shutdownNow(), timeout watchdogs, or application shutdown interrupting worker threads.","commonSituations":"Stopping a Kettle job via Thread.interrupt(); cancelling embedded execution in an app server; JVM shutdown hooks interrupting running transformation threads.","solutions":["Do not interrupt the thread waiting on the transformation; stop the transformation via trans.stopAll() instead","Restore the interrupt status in the caller (Thread.currentThread().interrupt()) and handle gracefully","Ensure executors are not shut down with shutdownNow() while transformations are awaited","Use a listener (TransListener) instead of a polling wait if interruption is expected"],"exampleFix":"// before\ntrans.execute(args);\ntrans.waitUntilFinished();\n// after: stop via API, not interruption\ntrans.execute(args);\nRuntime.getRuntime().addShutdownHook(new Thread(() -> trans.stopAll()));\ntrans.waitUntilFinished();","handlingStrategy":"try-catch","validationCode":"if (Thread.interrupted()) {\n  throw new IllegalStateException(\"Cannot wait for transformation: thread already interrupted\");\n}","typeGuard":"boolean wasInterruptedWhileWaiting(RuntimeException e) {\n  return \"Waiting for transformation to be finished interrupted!\".equals(e.getMessage()) && e.getCause() instanceof InterruptedException;\n}","tryCatchPattern":"try {\n  trans.waitUntilFinished();\n} catch (RuntimeException e) {\n  if (e.getCause() instanceof InterruptedException) {\n    Thread.currentThread().interrupt();\n    trans.stopAll();\n  } else throw e;\n}","preventionTips":["Use trans.stopAll() instead of Thread.interrupt() to cancel executions","Avoid shutdownNow() on executors that wait for transformations","Prefer TransListener/TransCompletedListener over polling waits","Preserve interrupt status in calling code"],"tags":["kettle","threading","interrupt"],"backgroundTag":"thread-interrupted","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"}