DayuanJiang/next-ai-draw-io · critical · Error
Server startup timeout after
Error message
Server startup timeout after ${timeout}ms What it means
waitForServer polls the Next.js server health endpoint every 100ms and throws when it does not become ready within the configured timeout (default ms in startNextServer).
Solutions
- Check the utilityProcess/server logs for the real startup crash
- Run npm run build before packaging/starting; verify serverPath exists
- Increase the timeout passed to waitForServer for slow machines
- Ensure the expected port is free (lsof -i) and the health check URL matches the bound port
Defensive patterns
Strategy: retry
Validate before calling
const started = await isPortResponsive(port) // quick TCP/health probe before assuming readiness
Try / catch
try {
await waitForServer(port, timeout)
} catch (e) {
if ((e as Error).message.includes('timeout')) {
showStartupDiagnostics(); captureUtilityProcessLogs()
}
} Prevention
- Run npm run build before launching/packaging
- Increase timeout on slower hardware
- Log utilityProcess stderr to catch the underlying crash early
- Free the expected port before start
When it happens
Trigger: Electron starts the Next.js standalone server as a utilityProcess and the server crashes on boot, takes too long to compile/bind the port, or the health endpoint path/port is wrong.
Common situations: Missing build output (running packaged app without npm run build), port already in use, crash inside next server startup, slow disk/AV scanning delaying startup, or timeout set too low.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of DayuanJiang/next-ai-draw-io@155ef4f7ac (2026-08-27).
Data as JSON: /api/errors/435735e6e7d22cc2.
Report an issue: GitHub.
Appendix: source
Thrown at electron/main/next-server.ts:41
}
/**
* Wait for the server to be ready by polling the health endpoint
*/
async function waitForServer(url: string, timeout = 30000): Promise<void> {
const start = Date.now()
while (Date.now() - start < timeout) {
try {
const response = await fetch(url)
if (response.ok || response.status < 500) {
return
}
} catch {
// Server not ready yet
}
await new Promise((resolve) => setTimeout(resolve, 100))
}
throw new Error(`Server startup timeout after ${timeout}ms`)
}
/**
* Start the Next.js standalone server using Electron's utilityProcess
* This API is designed for running Node.js code in the background
*/
export async function startNextServer(): Promise<string> {
const resourcePath = getResourcePath()
const serverPath = path.join(resourcePath, "server.js")
console.log(`Starting Next.js server from: ${resourcePath}`)
console.log(`Server script path: ${serverPath}`)
// Verify server script exists before attempting to start
if (!existsSync(serverPath)) {
throw new Error(
`Server script not found at ${serverPath}. ` +
"Please ensure the app was built correctly with 'npm run build'.",View on GitHub (pinned to 155ef4f7ac)