EADDRINUSE — the port is already in use

Decode the "address already in use" crash — Node's EADDRINUSE and Python's OSError errno 98 — understand why it happens when you get one public port, and bind it exactly once.

Your app crashes the moment it tries to listen, with a message about the address already being in use. It means something already grabbed the port you're trying to open. On Falix that "something" is almost always your own code binding the same port twice — this guide reads the verbatim error and shows you how to bind once and only once.

At a glance
Symptom App crashes at startup with "address already in use"
Cause Two things tried to listen on the same port
The rule One public port per server — bind it once, on 0.0.0.0

The verbatim error

Node throws an uncaught error and exits:

Error: listen EADDRINUSE: address already in use 0.0.0.0:25565
    at Server.setupListenHandle [as _listen2] (node:net:1908:16)
  code: 'EADDRINUSE',
  errno: -98,

Python raises the same thing from the standard library, with the Linux error number spelled out:

OSError: [Errno 98] Address already in use

EADDRINUSE and [Errno 98] are the same operating-system error under two names. Both mean: the port I asked for is already taken by another socket.

Why it happens on Falix

Your server gets one public port, handed to you as the SERVER_PORT environment variable (it's on the Network page too). That one port is the thing everything competes for. The realistic causes, in order of how often they bite:

Cause What it looks like in your code
Two listeners, one port An HTTP server and a separate WebSocket/second server both call .listen(SERVER_PORT)
A stray second listen() Copy-pasted startup code, or a library that also opens the port
A hard-coded port You listen on 3000 in one place and read SERVER_PORT in another — and they collide
A leftover process A previous run didn't fully release the port before a fast restart

🎯 Good to know: You can't dodge this by picking a different port number. You get exactly one public port; a second listener has nowhere else to go.

The fix

Bind once. Find every .listen(...) (Node) or .bind(...) / app.run(...) (Python) in your project. There should be one, and it should read SERVER_PORT and bind 0.0.0.0:

// Node — one listen, the whole app hangs off this server
const PORT = process.env.SERVER_PORT || 8080;
server.listen(PORT, '0.0.0.0', () => console.log('Listening on port ' + PORT));

If you need both HTTP and WebSockets, you do not open two ports — you attach the WebSocket server to the same HTTP server, so there's a single listen. That pattern lives in WebSockets.

Kill a leftover holder. If the port genuinely didn't release after a crash-restart loop, do a full Stop, wait for the server to reach Offline, then Start. A clean stop frees the port; a rapid auto-restart sometimes doesn't.

💡 Tip: The panel's console has a port-in-use diagnostic that spots this error and points you at the fix — one more reason to read the console from the top.

Prevention

  • One entry point owns the port. Structure your app so a single file opens the server and everything else imports from it. Two files each calling listen is the classic trap.
  • Never hard-code the port. Read SERVER_PORT everywhere; a literal like 3000 sitting next to SERVER_PORT is a collision waiting to happen — and it's also why your app might be unreachable.
  • Don't spawn a second copy. Forking a child process that also listens, or starting your app twice, guarantees this error. Run one process per server; for a genuinely separate app, give it its own Instance.

Next steps

Was this guide helpful?