NationalSecurityAgency/ghidra · error · EarlyTerminationException
The back-end exited (code=%s) before receiving a connection
Error message
The back-end exited (code=%s) before receiving a connection
What it means
Thrown as EarlyTerminationException by acceptOrSessionEnds when the back-end CompletableFuture completes (the launched target/tracer process exited) before the Trace RMI acceptor received an incoming connection. The exit code is included. This indicates the debugger back-end died during startup, before it could phone home to Ghidra.
Source
Thrown at Ghidra/Debug/Debugger-rmi-trace/src/main/java/ghidra/app/plugin/core/debug/gui/tracermi/launcher/AbstractTraceRmiLaunchOffer.java:578
SocketAddress address) throws Exception;
protected TraceRmiHandler acceptOrSessionEnds(DefaultTraceRmiAcceptor acceptor,
TraceRmiBackEnd backEnd)
throws SocketException, CancelledException, EarlyTerminationException {
acceptor.setTimeout(getConnectionTimeoutMillis());
CompletableFuture<TraceRmiHandler> futureConnection = CompletableFuture.supplyAsync(() -> {
try {
return acceptor.accept();
}
catch (CancelledException | IOException e) {
return ExceptionUtils.rethrow(e);
}
});
// Because of accept timeout, should be a finite wait
try {
CompletableFuture.anyOf(backEnd, futureConnection).get();
if (backEnd.isDone()) {
throw new EarlyTerminationException(
"The back-end exited (code=%s) before receiving a connection"
.formatted(backEnd.getNow(null)));
}
return futureConnection.get();
}
catch (ExecutionException e) {
switch (e.getCause()) {
case CancelledException ce -> throw ce;
default -> throw new AssertionError(e);
}
}
catch (InterruptedException e) {
throw new AssertionError(e);
}
}
public static class NoStaticMappingException extends Exception {
public NoStaticMappingException(String message) {View on GitHub (pinned to d5f144c24d)
Solutions
- Inspect the back-end terminal output for the error that caused the exit (the exit code is in the message).
- Verify the target binary path and all launch arguments in the launch offer configuration.
- Ensure required debugger/agent dependencies are installed and on PATH for the back-end.
- Confirm architecture compatibility between the debugger back-end and the target process.
Defensive patterns
Strategy: try-catch
Validate before calling
// Before launching, sanity-check the target binary and back-end dependencies
Path target = Path.of(spec.getArguments().get(0));
if (!Files.isExecutable(target)) throw new IllegalStateException("Target binary missing/not executable"); Try / catch
try { handler = acceptOrSessionEnds(acceptor, backEnd); }
catch (EarlyTerminationException e) {
// read exit code, surface back-end terminal output to user
throw e;
} Prevention
- Validate the target binary path and back-end dependencies before launch.
- Keep the back-end terminal visible so exit causes are obvious.
- Match debugger architecture to the target to avoid immediate back-end crashes.
When it happens
Trigger: The launch offer starts a back-end process and races its termination future against the RMI accept future. If the process exits first — crash, missing library, wrong architecture, bad arguments — this fires. Common with misconfigured launch arguments, missing target binary, or the back-end script erroring out immediately.
Common situations: The target executable path is wrong or the binary is missing; the back-end requires a dependency (e.g., gdb, a JDI agent jar) not installed; the launch arguments contain a typo causing immediate exit; the back-end script printed an error to its terminal and exited with a non-zero code; architecture mismatch (e.g., 32-bit target with 64-bit debugger).
Related errors
- Error connecting to ${address}: ${e}
- The resulting target process has no mapping to the static im
- Offer requires image, but no program given.
- No saved offers to launch {}
- Transaction already started
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/8320193bd2e87396.
Report an issue: GitHub.