{"record":{"id":"b147aa3665003582","repo":"pentaho/pentaho-kettle","slug":"command-execution-timed-out-after-timeoutms-ms","errorCode":null,"errorMessage":"Command execution timed out after ${timeoutMs}ms","messagePattern":"Command execution timed out after (.+?)ms","errorType":"exception","errorClass":"SshTimeoutException","httpStatus":null,"severity":"error","filePath":"engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java","lineNumber":460,"sourceCode":"        }\n\n        // Wait for the command to complete and exit status to be available\n        Set<ClientChannelEvent> events = ch.waitFor(\n          EnumSet.of( ClientChannelEvent.CLOSED ), timeoutMs );\n\n        // Give a bit more time for exit status to be set if the channel closed successfully\n        if ( events.contains( ClientChannelEvent.CLOSED ) ) {\n          // Try to get exit status with a short additional wait\n          Integer ex = ch.getExitStatus();\n          if ( ex == null ) {\n            // Wait a bit more for exit status to be set\n            Thread.sleep( 100 );\n            ex = ch.getExitStatus();\n          }\n          exit = ex == null ? -1 : ex;\n        } else {\n          // Timeout occurred\n          throw new SshTimeoutException( \"Command execution timed out after \" + timeoutMs + \"ms\" );\n        }\n      }\n      String outStr = stdout.toString( StandardCharsets.UTF_8 );\n      String errStr = stderr.toString( StandardCharsets.UTF_8 );\n      return new ExecResult( outStr, errStr, outStr + errStr, exit, exit != 0 );\n    } catch ( SshTimeoutException e ) {\n      throw e; // Re-throw timeout exceptions as-is\n    } catch ( InterruptedException e ) {\n      Thread.currentThread().interrupt(); // Restore interrupted status\n      throw new SshConnectionException( \"Command execution was interrupted\", e );\n    } catch ( Exception e ) {\n      throw new SshConnectionException( \"Failed to execute command: \" + command, e );\n    }\n  }\n\n  @Override\n  public ExecResult exec( String command ) throws SshConnectionException {\n    return exec( command, config.getCommandTimeoutMillis() );","sourceCodeStart":442,"sourceCodeEnd":478,"githubUrl":"https://github.com/pentaho/pentaho-kettle/blob/f3058517a153da500bf4551f46d79b91bf8ec552/engine/src/main/java/org/pentaho/di/core/ssh/mina/MinaSshConnection.java#L442-L478","documentation":"exec(command, timeoutMs) polls the channel's exit status and, when the wait window elapses before the remote command completes, throws SshTimeoutException('Command execution timed out after Nms'). The command may still be running remotely; the client simply stopped waiting.","triggerScenarios":"exec() is called with commandTimeoutMillis > 0 and the remote command does not produce an exit status within that period — long-running scripts, hung remote processes, or output waiting on a TTY prompt.","commonSituations":"Running backups/ETL scripts that exceed the default command timeout; remote command waiting on a password/passphrase prompt; remote host under load.","solutions":["Increase commandTimeoutMillis to exceed the command's worst-case duration","Fix the remote command to run non-interactively (no prompts, redirect stdin)","Run long jobs with nohup/background on the remote host and poll for completion","Verify the command is not blocked waiting for input (test interactively)","Break the work into smaller commands within the timeout window"],"exampleFix":"// before\nExecResult r = conn.exec( \"/opt/etl/run-all.sh\", 30000 ); // 30s, job takes minutes\n// after\nExecResult r = conn.exec( \"/opt/etl/run-all.sh\", 1800000 ); // 30min budget\n// or: nohup /opt/etl/run-all.sh > /tmp/etl.log 2>&1 & then poll","handlingStrategy":"try-catch","validationCode":"// estimate: ensure timeout exceeds worst-case command duration\nlong expectedMaxMillis = estimateCommandDuration( command );\nif ( config.getCommandTimeoutMillis() < expectedMaxMillis ) {\n  log.warn( \"Command timeout {}ms is below expected duration {}ms\", config.getCommandTimeoutMillis(), expectedMaxMillis );\n}","typeGuard":null,"tryCatchPattern":"try { result = conn.exec( cmd, timeoutMs ); }\ncatch ( SshTimeoutException e ) {\n  log.warn( \"Command exceeded {}ms; it may still be running remotely\", timeoutMs );\n  // optionally reconnect and kill/check the remote process before retrying\n}","preventionTips":["Size the timeout from the command's worst-case runtime, not its average","Make remote commands non-interactive (no prompts)","Run long jobs in the background on the host and poll for completion","Monitor execution times to recalibrate timeouts"],"tags":["ssh","timeout","command-execution"],"backgroundTag":"request-timeout","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"}