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

  1. Use the returned publicUrl (worker route) instead of the direct trycloudflare URL — it is verified healthy.
  2. Wait 1–5 minutes for trycloudflare DNS propagation and re-probe the direct URL.
  3. Switch the client environment's DNS (e.g. 1.1.1.1) if *.trycloudflare.com is blocked by the local resolver/firewall.
  4. 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

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


AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30). Data as JSON: /api/errors/e83df035f0352488. Report an issue: GitHub.