remix-run/react-router · critical · Error

No available port found

Error message

No available port found

What it means

Thrown by the `react-router-serve` CLI when neither the preferred port nor an OS-assigned port (port 0) can be bound. `checkPort` resolves `undefined` for `EADDRINUSE` or `EACCES`, so both failing means the host has no bindable TCP port to hand back.

Source

Thrown at packages/react-router-serve/cli.ts:80

  );
}

function parseNumber(raw?: string) {
  if (raw === undefined) return undefined;
  let maybe = Number(raw);
  if (Number.isNaN(maybe)) return undefined;
  return maybe;
}

async function getAvailablePort(
  preferredPort: number,
  host?: string,
): Promise<number> {
  let preferredAvailablePort = await checkPort(preferredPort, host);
  let availablePort = preferredAvailablePort ?? (await checkPort(0, host));

  if (availablePort === undefined) {
    throw new Error("No available port found");
  }

  return availablePort;
}

function checkPort(port: number, host?: string): Promise<number | undefined> {
  return new Promise((resolve, reject) => {
    let server = net.createServer();
    let listenOptions = host ? { port, host } : { port };

    server.unref();

    server.once("error", (error: NodeJS.ErrnoException) => {
      if (error.code === "EADDRINUSE" || error.code === "EACCES") {
        resolve(undefined);
      } else {
        reject(error);
      }

View on GitHub (pinned to 1fd704a7da)

Solutions

  1. Free or kill whatever holds the ports (e.g. `lsof -i :PORT`, `pkill node`) and retry.
  2. Pass an explicit free port via the CLI `--port` flag or `PORT` env var.
  3. If in a container, ensure the exposed port range permits unprivileged binds and that the ephemeral range is not exhausted.
  4. Run as a user with bind permission for the requested port, or pick a port >1024.
Defensive patterns

Strategy: try-catch

Validate before calling

import net from 'node:net';
async function isPortFree(port: number, host?: string): Promise<boolean> {
  return new Promise((resolve) => {
    const s = net.createServer();
    s.once('error', () => resolve(false));
    s.listen({ port, host }, () => s.close(() => resolve(true)));
  });
}
// before starting the server:
if (!(await isPortFree(port, host))) {
  console.error(`Port ${port} is busy, choose another with --port`);
  process.exit(1);
}

Try / catch

try {
  await run();
} catch (e) {
  if (e instanceof Error && e.message === 'No available port found') {
    console.error('No bindable port: free a port or pass --port');
    process.exit(1);
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling `react-router-serve` (or `getAvailablePort`) on a machine where every attempted port returns EADDRINUSE/EACCES, including the ephemeral-range fallback from `checkPort(0)`. Also triggered by an environment where the unprivileged port range is exhausted or where the process lacks permission to bind any port.

Common situations: Running inside a hardened container/CI sandbox with a restricted port set; SELinux/AppArmor denying the bind; extremely high fd usage leaving no ephemeral ports; a misconfigured `--port` flag pointing at a privileged port (<1024) as a non-root user combined with an ephemeral-range exhaustion.

Related errors


AI-assisted analysis of remix-run/react-router@1fd704a7da (2026-08-12). Data as JSON: /api/errors/5d01078cc1f87cba. Report an issue: GitHub.