decolua/9router · info
[Tunnel] direct URL not reachable yet, continuing via public
Error message
[Tunnel] direct URL not reachable yet, continuing via publicUrl
What it means
After a quick tunnel is enabled, enableTunnel verifies the public worker URL first (reliable), then probes the direct *.trycloudflare.com URL best-effort. If the direct probe fails — because DNS propagation for the freshly minted trycloudflare hostname lags or is blocked — this warning is logged and enablement still succeeds, returning publicUrl as the working entry point.
Source
Thrown at src/lib/tunnel/cloudflare/manager.js:95
if (onUnexpectedExit) onUnexpectedExit();
});
const { tunnelUrl } = await spawnQuickTunnel(localPort, onUrlUpdate);
console.log(`[Tunnel] spawned: ${tunnelUrl}`);
throwIfCancelled(token);
const publicUrl = `https://r${shortId}.abc-tunnel.us`;
await registerTunnelUrl(shortId, tunnelUrl);
saveState({ shortId, tunnelUrl });
await updateSettings({ tunnelEnabled: true, tunnelUrl });
console.log(`[Tunnel] registered shortId=${shortId} publicUrl=${publicUrl}`);
// Verify publicUrl first (worker route is reliable; direct *.trycloudflare.com DNS may lag)
await waitForHealth(publicUrl, token);
console.log("[Tunnel] public URL healthy");
// Direct tunnel probe is best-effort: DNS for *.trycloudflare.com can be slow/blocked
if (!(await probeUrlAlive(tunnelUrl))) {
console.warn("[Tunnel] direct URL not reachable yet, continuing via publicUrl");
} else {
console.log("[Tunnel] direct URL healthy");
}
console.log("[Tunnel] enable success");
return { success: true, tunnelUrl, shortId, publicUrl };
} catch (e) {
// Suppress noise when spawn was deliberately killed (restart/disable superseded it)
if (!/cloudflared killed|tunnel cancelled/.test(e.message)) {
console.error(`[Tunnel] enable error: ${e.message}`);
}
throw e;
} finally {
svc.spawnInProgress = false;
}
}
export async function disableTunnel() {View on GitHub (pinned to 90b52e06ff)
Solutions
- Use the returned publicUrl (worker route) instead of the direct trycloudflare URL — it is verified healthy.
- Wait 1–5 minutes for trycloudflare DNS propagation and re-probe the direct URL.
- Switch the client environment's DNS (e.g. 1.1.1.1) if *.trycloudflare.com is blocked by the local resolver/firewall.
- If the direct URL must work, restart tunnel enablement to mint a fresh hostname after fixing network egress.
Defensive patterns
Strategy: fallback
Validate before calling
// verify which URL is usable before pointing clients at it
async function pickUrl(publicUrl, directUrl) {
for (const url of [directUrl, publicUrl]) {
try { const r = await fetch(url + "/health"); if (r.ok) return url; } catch {}
}
return publicUrl;
} Prevention
- Always use the returned publicUrl as the canonical entry point.
- Allow a few minutes for trycloudflare DNS propagation before sharing the direct URL.
- Whitelist *.trycloudflare.com in corporate DNS/proxies if the direct URL is needed.
- Re-check direct reachability after network/VPN changes.
When it happens
Trigger: probeUrlAlive(tunnelUrl) returns false right after a new quick tunnel is created: fresh hostname DNS not propagated yet, local resolver cache, or network blocking trycloudflare.com while the worker route works.
Common situations: Corporate DNS filtering *.trycloudflare.com; first minutes after tunnel creation; VPN/proxy interference; clients configured to hit the direct URL seeing failures until DNS settles.
Related errors
- Health check timeout after ${HEALTH_CHECK.timeoutMs}ms
- cancelled
- Health check timeout after ${HEALTH_CHECK.timeoutMs}ms
- [Tunnel] cloudflared exited unexpectedly, scheduling respawn
- [ProxyFetch] Proxy required but failed (strictProxy=true): $
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/e83df035f0352488.
Report an issue: GitHub.