heygen-com/hyperframes · error
No free port found in [${startPort}, ${startPort + 9}]
Error message
No free port found in [${startPort}, ${startPort + 9}] What it means
listenOnFreePort scans 10 consecutive ports starting at startPort; each EADDRINUSE causes a continue to the next candidate. The error fires only after all 10 (startPort .. startPort+9) are in use, or a non-EADDRINUSE error was re-thrown earlier. The function is used by the play/present dev servers to bind a preview port.
Source
Thrown at packages/cli/src/utils/compositionServer.ts:165
const onErr = (err?: NodeJS.ErrnoException) => {
server.removeListener("listening", onOk);
rej(err ?? new Error("server error"));
};
const onOk = () => {
server.removeListener("error", onErr);
res();
};
server.once("error", onErr);
server.once("listening", onOk);
server.listen(port);
});
return port;
} catch (err: unknown) {
if ((err as NodeJS.ErrnoException).code === "EADDRINUSE") continue;
throw err;
}
}
throw new Error(`No free port found in [${startPort}, ${startPort + 9}]`);
}
View on GitHub (pinned to c2996c8626)
Solutions
- Free the ports: identify and kill processes holding startPort..startPort+9 (lsof -i :3000-3009 or netstat).
- Pass a different startPort in a less-contended range (e.g. 49152+, the ephemeral band).
- Reduce the number of concurrent preview servers running on the same host.
- Wait for TIME_WAIT to clear (usually 30-60s) if a preview was just stopped, then retry.
Defensive patterns
Strategy: retry
Validate before calling
import { createServer } from 'node:net';
async function isPortFree(port: number): Promise<boolean> {
return new Promise((res) => {
const s = createServer();
s.once('error', () => res(false));
s.once('listening', () => { s.close(() => res(true)); });
s.listen(port);
});
}
// probe a candidate startPort before passing it in
const ok = await isPortFree(startPort);
if (!ok) throw new Error(`Port ${startPort} busy; choose another.`); Try / catch
try {
return await listenOnFreePort(server, startPort);
} catch (err) {
if (err instanceof Error && /No free port found/.test(err.message)) {
// shift to a less-contended range and retry once
return listenOnFreePort(server, 49152);
}
throw err;
} Prevention
- Kill orphaned preview servers between runs (lsof -i:<port>).
- Use a startPort in the ephemeral range (49152+) where contention is lower.
- Avoid running many concurrent dev servers on adjacent ports.
When it happens
Trigger: Calling listenOnFreePort with a startPort whose entire 10-port window is occupied — e.g. startPort=3000 and 3000-3009 all bound by other dev servers, browser instances, or orphaned hyperframes processes. Also when a previous preview server did not release its port (TIME_WAIT or unref'd process still holding the socket).
Common situations: Many dev servers running on adjacent ports; a hung/orphaned hyperframes preview from a previous run; Docker/WSL port forwarding consuming the range; CI runners with many concurrent preview builds sharing a port band.
Related errors
- background preview did not become ready; see ${logPath}
- background preview did not stop for ${resolve(projectDir)}
- [build-zip] npm install into staging failed (status ${result
- Model download failed: ${model}
- OpenRouter request failed with HTTP ${res.status}
AI-assisted analysis of heygen-com/hyperframes@c2996c8626 (2026-08-12).
Data as JSON: /api/errors/2923b7b9e507bb69.
Report an issue: GitHub.