remix-run/react-router · error
No available port found
Error message
No available port found
What it means
@react-router/serve's CLI resolves its listen port by probing the preferred port and then an ephemeral port (0). checkPort resolves undefined for EADDRINUSE and EACCES — skipping to the next candidate — and the fallback to port 0 normally always succeeds. 'No available port found' means even the ephemeral probe came back undefined, i.e. the process is denied socket binding outright (permission-denied on every attempt) in the current environment.
Solutions
- Relax the sandbox: run the container with default network capabilities instead of --cap-drop ALL style lockdown
- Check SELinux/AppArmor or firewall policy for socket-bind denials for the node process
- If you only meant to change interfaces, verify the --host value is an address this machine actually owns
Example fix
# before — binding denied by container lockdown docker run --cap-drop ALL --network none my-app \ npx react-router-serve ./build/server/index.js # after — allow basic networking docker run my-app \ npx react-router-serve ./build/server/index.js
Defensive patterns
Strategy: retry
Validate before calling
// probe candidates (incl. ephemeral) before handing off to the server
import net from "node:net";
function probe(port: number, host?: string): Promise<number | undefined> {
return new Promise((resolve) => {
const s = net.createServer();
s.once("error", () => resolve(undefined));
s.listen(host ? { port, host } : { port }, () => {
const addr = s.address();
s.close(() => resolve(typeof addr === "object" && addr ? addr.port : undefined));
});
});
}
if ((await probe(0, host)) === undefined) {
throw new Error("socket binding denied in this environment — fix sandbox/network policy");
} Try / catch
// your own server bootstrap: walk candidate ports, treat denial separately
for (const port of [Number(process.env.PORT) || 3000, 3001, 0]) {
try {
await listen(port, host);
break;
} catch (err) {
const code = (err as NodeJS.ErrnoException).code;
if (code !== "EADDRINUSE") throw err; // EACCES/EADDRNOTAVAIL need a host/env fix, not a retry
}
} Prevention
- Don't drop all network capabilities from containers that must serve HTTP
- Verify --host is an address the machine owns before binding
- Probe with port 0 in a preflight step to detect binding denial early
When it happens
Trigger: Running react-router-serve in an environment where net.createServer().listen() fails with EACCES for both the preferred port and port 0 — e.g. a locked-down container/sandbox without network capabilities, or an OS policy denying socket creation.
Common situations: Hardened Docker/Kubernetes containers (network caps dropped), gVisor/Firecracker sandboxes, SELinux/AppArmor policies, CI runners with networking restricted, or non-root users denied socket ops.
Related errors
- There was a problem extracting the file from the provided…
- There was a problem fetching the file
- " " is an invalid template. Run to see supported template…
- Exiting to avoid overwriting files
- File collisions detected in a non-interactive environment
AI-assisted analysis of remix-run/react-router@6beaca3952 (2026-08-18).
Data as JSON: /api/errors/5d01078cc1f87cba.
Report an issue: GitHub.
Appendix: 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 6beaca3952)