NationalSecurityAgency/ghidra · critical · RuntimeException
Could not start server
Error message
Could not start server
What it means
DapServer.startServer wraps an IOException from new ServerSocket(port, 50, address) in a RuntimeException('Could not start server' + e.getMessage()). The server socket could not be bound, so the Debug Adapter Protocol listener thread never starts. The cause message is concatenated into the thrown message (no exception chaining, so the stack trace loses the original IOException as a cause).
Source
Thrown at Ghidra/Debug/Debugger-dap/src/main/java/dap/DapServer.java:63
this.port = plugin.getPort();
}
public void startServer() {
if (running) {
return;
}
try {
if (server != null && !server.isClosed()) {
server.close();
}
server = new ServerSocket(port, 50, address);
this.running = true;
this.listenerThread = new Thread(this, "DAP-Server-Listener");
this.listenerThread.start();
}
catch (IOException e) {
throw new RuntimeException("Could not start server" + e.getMessage());
}
}
public void stopServer() {
if (!running) {
return;
}
running = false;
if (server != null) {
try {
if (!server.isClosed()) {
server.close();
}
}
catch (IOException e) {
Msg.warn(this, "Error closing server socket: " + e.getMessage());
}View on GitHub (pinned to d5f144c24d)
Solutions
- Free or change the port: pick an unused port for the DAP server before calling startServer().
- Ensure a previous DapServer instance was stopped via stopServer() and its ServerSocket closed (check running flag / isClosed).
- Use a non-privileged port and bind to a valid local address (e.g. loopback).
- If the message is truncated, reproduce with a direct ServerSocket bind to see the real IOException (BindException, etc.).
Example fix
// before
public void startServer() {
try {
server = new ServerSocket(port, 50, address);
...
} catch (IOException e) {
throw new RuntimeException("Could not start server" + e.getMessage());
}
}
// after
public void startServer() throws IOException {
try {
server = new ServerSocket(port, 50, address);
} catch (IOException e) {
throw new IOException("Could not start server on " + address + ":" + port, e);
}
...
} Defensive patterns
Strategy: try-catch
Validate before calling
try (ServerSocket probe = new ServerSocket(port, 50, address)) {
// port is free; close probe then let DapServer bind
} catch (IOException e) {
// port unavailable; choose another port before startServer()
} Try / catch
try {
server.startServer();
} catch (RuntimeException e) {
// startServer wraps IOException; report bind failure and pick a new port
} Prevention
- Always stopServer() and confirm the socket is closed before restarting.
- Pick a high, non-privileged, likely-free port for DAP.
- Bind to a valid local address (loopback) to avoid address-related bind failures.
When it happens
Trigger: startServer() is invoked when the requested TCP port is already in use, the bind address is not valid on the host, or the OS refuses the bind (privileged port without permission, or port exhausted). The bind happens before the listener thread is started, so the failure is immediate.
Common situations: A previous DAP server instance did not shut down and still holds the port; another application occupies the configured port; trying to bind to a privileged port (<1024) as a non-root user; binding to an address that does not exist on the machine.
Related errors
- Could not start server
- port must be numeric
- address must be 'port' or 'host:port'
- Usage: ghidra trace connect ADDRESS
- ADDRESS must be HOST:PORT
AI-assisted analysis of NationalSecurityAgency/ghidra@d5f144c24d (2026-08-14).
Data as JSON: /api/errors/4266da94a2dacbb1.
Report an issue: GitHub.