{"record":{"id":"554bc40d08ddf160","repo":"decolua/9router","slug":"tunnel-cloudflared-exited-unexpectedly-scheduli","errorCode":null,"errorMessage":"[Tunnel] cloudflared exited unexpectedly, scheduling respawn","messagePattern":"\\[Tunnel\\] cloudflared exited unexpectedly, scheduling respawn","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"src/lib/tunnel/cloudflare/manager.js","lineNumber":76,"sourceCode":"\n    killCloudflared(localPort);\n    console.log(\"[Tunnel] killed existing cloudflared\");\n    throwIfCancelled(token);\n\n    const existing = loadState();\n    const shortId = existing?.shortId || generateShortId();\n\n    const onUrlUpdate = async (url) => {\n      if (token.cancelled) return;\n      console.log(`[Tunnel] url updated: ${url}`);\n      await registerTunnelUrl(shortId, url);\n      saveState({ shortId, tunnelUrl: url });\n      await updateSettings({ tunnelEnabled: true, tunnelUrl: url });\n    };\n\n    // Register exit handler BEFORE spawn so it fires even on early exit\n    setUnexpectedExitHandler(() => {\n      console.warn(\"[Tunnel] cloudflared exited unexpectedly, scheduling respawn\");\n      if (onUnexpectedExit) onUnexpectedExit();\n    });\n\n    const { tunnelUrl } = await spawnQuickTunnel(localPort, onUrlUpdate);\n    console.log(`[Tunnel] spawned: ${tunnelUrl}`);\n    throwIfCancelled(token);\n\n    const publicUrl = `https://r${shortId}.abc-tunnel.us`;\n    await registerTunnelUrl(shortId, tunnelUrl);\n    saveState({ shortId, tunnelUrl });\n    await updateSettings({ tunnelEnabled: true, tunnelUrl });\n    console.log(`[Tunnel] registered shortId=${shortId} publicUrl=${publicUrl}`);\n\n    // Verify publicUrl first (worker route is reliable; direct *.trycloudflare.com DNS may lag)\n    await waitForHealth(publicUrl, token);\n    console.log(\"[Tunnel] public URL healthy\");\n    // Direct tunnel probe is best-effort: DNS for *.trycloudflare.com can be slow/blocked\n    if (!(await probeUrlAlive(tunnelUrl))) {","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/decolua/9router/blob/90b52e06ffd666b7929554211474d01588f6b1f8/src/lib/tunnel/cloudflare/manager.js#L58-L94","documentation":"During enableTunnel, the manager registers an unexpected-exit handler BEFORE spawning cloudflared so that even a crash-on-startup triggers it. When the spawned cloudflared process exits without being asked to stop, this warning is logged and the registered onUnexpectedExit callback schedules a respawn of the tunnel. It means the tunnel process died and automatic recovery is underway.","triggerScenarios":"cloudflared terminates on its own during or after spawnQuickTunnel: binary missing/corrupt, network dropped, Cloudflare edge connection closed, port conflict, OOM kill, or early-exit due to bad flags. Also fires after an external 'taskkill cloudflared' or systemd/launchd interference.","commonSituations":"Laptops sleeping/waking and killing the process; corporate firewalls blocking Cloudflare egress; cloudflared not installed or wrong arch binary; running multiple instances fighting over cloudflared; VPN dropping mid-session.","solutions":["Wait — the handler schedules a respawn automatically; verify a new '[Tunnel] spawned: <url>' line follows.","Verify the cloudflared binary exists and is executable (and matches OS/arch); reinstall if needed.","Check outbound network/VPN/firewall to Cloudflare edge (trycloudflare.com) and retry enabling the tunnel.","Ensure no other process manages/kills cloudflared (duplicate tray/daemon instances) and that the local port is not occupied."],"exampleFix":"// before: cloudflared not on PATH → spawn exits instantly, respawn loop\nconst { tunnelUrl } = await spawnQuickTunnel(localPort, onUrlUpdate);\n// after: pre-check binary before enabling\nif (!spawnSync(\"cloudflared\", [\"--version\"], { stdio: \"ignore\" }).error) {\n  const { tunnelUrl } = await spawnQuickTunnel(localPort, onUrlUpdate);\n}","handlingStrategy":"retry","validationCode":"// ensure cloudflared is available before enabling the tunnel\nimport { spawnSync } from \"child_process\";\nconst check = spawnSync(\"cloudflared\", [\"--version\"], { stdio: \"ignore\" });\nif (check.error) throw new Error(\"cloudflared not installed or not on PATH\");","typeGuard":null,"tryCatchPattern":"// tolerate transient exits; rely on auto-respawn, alert only on repeated failures\nlet respawnCount = 0;\nsetUnexpectedExitHandler(() => {\n  if (++respawnCount > 5) console.error(\"[Tunnel] repeated cloudflared crashes — check binary/network\");\n});","preventionTips":["Install the correct cloudflared binary for your OS/arch and keep it on PATH.","Ensure stable network egress to Cloudflare (no blocking VPN/firewall).","Avoid running multiple instances that manage the same cloudflared process.","Prevent system sleep/suspend during tunnel use."],"tags":["tunnel","cloudflare","process-crash","network","respawn"],"backgroundTag":"tunnel-process-exited-unexpectedly","analyzedSha":"90b52e06ffd666b7929554211474d01588f6b1f8","analyzedAt":"2026-08-30T21:05:45.952Z","schemaVersion":2},"datasetVersion":"2026-08-30T23:17:21.991Z"}