xpipe-io/xpipe · error · BeaconServerException

failure.getThrowable()

Error message

failure.getThrowable()

What it means

In TerminalLaunchRequest.waitForCompletion(), when the terminal launch finishes with a ResultFailure, the underlying throwable is extracted and rethrown wrapped in a BeaconServerException. This propagates the actual cause of a failed terminal launch (raised on the beacon/server side) back to the caller of sshLaunchExchange/waitExchange instead of silently swallowing it.

Source

Thrown at app/src/main/java/io/xpipe/app/terminal/TerminalLaunchRequest.java:67

        this.workingDirectory = workingDirectory;
        this.shellPid = -1;
    }

    public Path waitForCompletion() throws BeaconServerException {
        while (true) {
            if (latch.getCount() > 0) {
                ThreadHelper.sleep(10);
                continue;
            }

            if (getResult() == null) {
                throw ErrorEventFactory.expected(new BeaconServerException("Launch request aborted"));
            }

            var r = getResult();
            if (r instanceof TerminalLaunchResult.ResultFailure failure) {
                var t = failure.getThrowable();
                throw new BeaconServerException(t);
            }

            return ((TerminalLaunchResult.ResultSuccess) r).getTargetScript();
        }
    }

    public void setupRequestAsync() {
        if (latch == null || latch.getCount() == 0) {
            latch = new CountDownLatch(1);
        }
        ThreadHelper.runAsync(() -> {
            setupRequest();
            latch.countDown();
        });
    }

    public void abort() {
        latch.countDown();

View on GitHub (pinned to d85ca821ba)

Solutions

  1. Inspect the cause (failure.getThrowable()) in the BeaconServerException to find the real launch failure
  2. Fix the underlying terminal launch problem (script path, shell command, permissions)
  3. Re-run the launch and ensure the request completes with ResultSuccess
  4. Check that the target script content is valid for the target shell

Example fix

// before
doTerminalLaunch(script); // may complete as ResultFailure
// after
try {
    doTerminalLaunch(script);
} catch (BeaconServerException e) {
    // e.getCause() is the original launch throwable; fix and retry
    log.error("Terminal launch failed", e.getCause());
}
Defensive patterns

Strategy: try-catch

Validate before calling

// check result state before unwrapping
var r = request.getResult();
boolean failed = r instanceof TerminalLaunchResult.ResultFailure;

Type guard

if (r instanceof TerminalLaunchResult.ResultFailure failure) { /* handle failure.getThrowable() */ }

Try / catch

try {
    request.waitForCompletion();
} catch (BeaconServerException e) {
    Throwable cause = e.getCause(); // original terminal launch failure
    handleLaunchFailure(cause);
}

Prevention

When it happens

Trigger: A terminal launch request registered with TerminalLauncherManager completes with TerminalLaunchResult.ResultFailure (e.g. the spawned shell or target script failed), and the caller invokes waitForCompletion() (via sshLaunchExchange or waitExchange).

Common situations: Target script execution error on the remote/local terminal; shell exited before handshake; launch aborted on the server side; permission or command-not-found errors during terminal startup surfaced through the beacon protocol.

Related errors


AI-assisted analysis of xpipe-io/xpipe@d85ca821ba (2026-09-06). Data as JSON: /api/errors/4f8be526e232b246. Report an issue: GitHub.