Node "listen EACCES permission denied" on a Privileged Port in CI - Fix It
listen EACCES means the process tried to bind a port it is not allowed to use. Ports below 1024 are privileged and a non-root CI user cannot bind them.
What this error means
A server start in CI throws Error: listen EACCES: permission denied 0.0.0.0:80 (or another low port) because the unprivileged runner user may not bind privileged ports.
Error: listen EACCES: permission denied 0.0.0.0:80
at Server.setupListenHandle [as _listen2] (node:net:1792:21)
at listenInCluster (node:net:1865:12) {
code: 'EACCES', port: 80
}Common causes
Binding a port below 1024 as a non-root user
Privileged ports require elevated capability; the CI runner user lacks it, so the bind is denied.
A hardcoded production port in tests
Test config reuses the production port (80 or 443) instead of an unprivileged test port.
How to fix it
Use an unprivileged port
- Bind to a port above 1024 (or 0 for ephemeral) in the CI environment.
- Drive the port from an env var so production keeps its low port.
const port = Number(process.env.PORT) || 3000;
server.listen(port);How to prevent it
- Read the listen port from configuration, default tests to an unprivileged or ephemeral port, and never hardcode privileged ports into code that runs as a non-root CI user.