decolua/9router · error
EADDRINUSE
EADDRINUSE
Error message
Port ${LOCAL_PORT} already in use What it means
The MITM proxy server fails to bind its local listening port because another socket already holds it (errno EADDRINUSE). The server logs 'Port <LOCAL_PORT> already in use' and exits with code 1.
Source
Thrown at src/mitm/server.js:385
}
});
log(`Killed ${pidList.length} process(es) on port ${port}`);
} catch (e) {
if (e.status !== 1) throw e;
}
}
try {
killPort(LOCAL_PORT);
} catch (e) {
err(`Cannot kill process on port ${LOCAL_PORT}: ${e.message}`);
process.exit(1);
}
server.listen(LOCAL_PORT, () => log(`🚀 Server ready on :${LOCAL_PORT}`));
server.on("error", (e) => {
if (e.code === "EADDRINUSE") err(`Port ${LOCAL_PORT} already in use`);
else if (e.code === "EACCES") err(`Permission denied for port ${LOCAL_PORT}`);
else err(e.message);
process.exit(1);
});
const { removeAllDNSEntriesSync } = require("./dns/dnsConfig");
let isShuttingDown = false;
const shutdown = () => {
if (isShuttingDown) return;
isShuttingDown = true;
// Strip tool hosts from /etc/hosts so other apps aren't broken after exit
removeAllDNSEntriesSync();
const forceExit = setTimeout(() => process.exit(0), 1500);
server.close(() => { clearTimeout(forceExit); process.exit(0); });
};
process.on("SIGTERM", shutdown);
process.on("SIGINT", shutdown);
if (process.platform === "win32") process.on("SIGBREAK", shutdown);View on GitHub (pinned to 90b52e06ff)
Solutions
- Find and stop the process holding the port: lsof -i :<LOCAL_PORT> (or netstat) and kill the stale instance.
- Restart the tray/launcher which automatically kills processes LISTENING on LOCAL_PORT before starting.
- Change LOCAL_PORT (env/config) to a free port if the collision is with another service.
- Wait a moment and retry — TIME_WAIT sockets usually clear within a minute.
Example fix
// before PORT=20128 (same as gateway) → EADDRINUSE // after MITM_LOCAL_PORT=20129 npm run start # distinct from gateway port
Defensive patterns
Strategy: validation
Validate before calling
const net = require('net');
const port = Number(process.env.MITM_LOCAL_PORT || LOCAL_PORT);
const probe = net.createServer().once('error', (e) => {
if (e.code === 'EADDRINUSE') console.error(`Port ${port} in use — pick another or stop the other instance`);
});
probe.listen(port, () => probe.close(() => startServer(port))); Try / catch
server.on('error', (e) => {
if (e.code === 'EADDRINUSE') {
err(`Port ${LOCAL_PORT} already in use`);
// optionally retry once after killing stale listeners on LOCAL_PORT
process.exit(1);
}
}); Prevention
- Run only one MITM instance — use the tray/launcher rather than manual starts.
- Choose a LOCAL_PORT distinct from the gateway port (20128).
- Probe port availability with a temporary net.createServer before binding.
- Ensure previous instances are killed on shutdown (the server already kills LISTENERS on LOCAL_PORT at startup).
When it happens
Trigger: server.listen(LOCAL_PORT) while another 9Router MITM instance, the gateway itself, or any unrelated process is already bound to the same local port.
Common situations: Two MITM instances launched (e.g. tray + manual); previous instance not fully shut down (lingering listener, the code even kills LISTENING processes on LOCAL_PORT for this reason); LOCAL_PORT collides with the gateway port 20128 or another dev server.
Related errors
- MITM server failed to start. ${reason}
- Machine ID is required for Cursor API
- http2 module not available
- HTTP/2 is required for Cursor AgentService (endpoint is h2-o
- Cursor AgentService endpoint is not configured
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/a02d2fcd20eba62d.
Report an issue: GitHub.