jenkinsci/jenkins · error · SocketTimeoutException

Failed to retrieve command result in time

Error message

Failed to retrieve command result in time: {}

What it means

SocketTimeoutException thrown by SSHCLI when channel.waitFor(ClientChannelEvent.CLOSED, 0L) returns a mask containing TIMEOUT. The SSH exec channel did not close within the wait, so no exit status could be obtained for the command.

Solutions

  1. Confirm the command is expected to terminate; if it is long-running, run it asynchronously or increase the effective timeout.
  2. Ensure stdin is closed/redirected (</dev/null) so the remote command does not block waiting for input.
  3. Check SSH/network health and that the controller is responsive (not GC-thrashing or deadlocked).

Example fix

# before: command may block on stdin
java -jar jenkins-cli.jar -ssh -s jenkins help
# after: close stdin so the channel can terminate
echo '' | java -jar jenkins-cli.jar -ssh -s jenkins help
# or: java -jar jenkins-cli.jar -ssh -s jenkins help </dev/null
Defensive patterns

Strategy: retry

Validate before calling

// Before running, sanity-check the controller is responsive over SSH
try (ClientSession s = client.connect(UserAuth, host, port).verify(10, TimeUnit.SECONDS).getSession()) {
    s.auth().verify(10000L);
} // reachable; proceed to run the command

Try / catch

try {
    channel.waitFor(List.of(ClientChannelEvent.CLOSED), timeout);
} catch (SocketTimeoutException e) {
    // optionally retry once, then report the command did not finish in time
}

Prevention

When it happens

Trigger: The remote Jenkins SSH command hangs (long-running operation, waiting on a lock, or prompting for input that never arrives), or the network stalls so the channel never receives EOF/CLOSED.

Common situations: Running a CLI command that triggers a long job/lock on the controller; SSH keepalive not configured so a dead connection lingers; command blocked on stdin that the client never sends/closes.

Related errors


AI-assisted analysis of jenkinsci/jenkins@2e228ff40b (2026-08-14). Data as JSON: /api/errors/80a493113c0731d6. Report an issue: GitHub.

Appendix: source

Thrown at cli/src/main/java/hudson/cli/SSHCLI.java:113

            cf.await();
            try (ClientSession session = cf.getSession()) {
                for (KeyPair pair : provider.getKeys()) {
                    CLI.LOGGER.log(FINE, "Offering {0} private key", pair.getPrivate().getAlgorithm());
                    session.addPublicKeyIdentity(pair);
                }
                session.auth().verify(10000L);

                try (ClientChannel channel = session.createExecChannel(command.toString())) {
                    channel.setIn(new NoCloseInputStream(System.in));
                    channel.setOut(new NoCloseOutputStream(System.out));
                    channel.setErr(new NoCloseOutputStream(System.err));
                    WaitableFuture wf = channel.open();
                    wf.await();

                    Set<ClientChannelEvent> waitMask = channel.waitFor(List.of(ClientChannelEvent.CLOSED), 0L);

                    if (waitMask.contains(ClientChannelEvent.TIMEOUT)) {
                        throw new SocketTimeoutException("Failed to retrieve command result in time: " + command);
                    }

                    Integer exitStatus = channel.getExitStatus();
                    return exitStatus;

                }
            } finally {
                client.stop();
            }
        }
    }

    @SuppressFBWarnings(value = "URLCONNECTION_SSRF_FD", justification = "Client-side code doesn't involve SSRF.")
    private static URLConnection openConnection(URL url) throws IOException {
        return url.openConnection();
    }

    private SSHCLI() {}

View on GitHub (pinned to 2e228ff40b)