decolua/9router · error · Error

Failed to start proxy

Error message

Failed to start proxy

What it means

handleHeadroomStart throws this when POST /api/headroom/start responds non-2xx and its body has no `error` field. It signals the token-saver proxy failed to start; the message is stored in headroomActionError and displayed in the UI.

Source

Thrown at src/app/(dashboard)/dashboard/token-saver/TokenSaverClient.js:191

        loading: false,
      });
      setHeadroomExtras({
        version: null,
        extras: { code: false, ml: false },
        available: ["code", "ml"],
        loading: false,
      });
      setPendingExtras([]);
    }
  }, []);

  const handleHeadroomStart = useCallback(async () => {
    setHeadroomActionError("");
    setHeadroomActionLoading(true);
    try {
      const res = await fetch("/api/headroom/start", { method: "POST" });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || "Failed to start proxy");
      await refreshHeadroomStatus();
    } catch (e) {
      setHeadroomActionError(e.message);
    } finally {
      setHeadroomActionLoading(false);
    }
  }, [refreshHeadroomStatus]);

  const handleHeadroomStop = useCallback(async () => {
    setHeadroomActionLoading(true);
    try {
      await fetch("/api/headroom/stop", { method: "POST" });
      await refreshHeadroomStatus();
    } finally {
      setHeadroomActionLoading(false);
    }
  }, [refreshHeadroomStatus]);

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Read the server's actual error body/status for /api/headroom/start in the network tab
  2. Check whether the headroom proxy port is already in use (lsof/netstat) and free it
  3. Install the headroom extras first if status shows available but not installed
  4. Check server logs for spawn/permission errors on the proxy executable

Example fix

// before
if (!res.ok) throw new Error(data.error || "Failed to start proxy");
// after
if (!res.ok) throw new Error(data.error || `Failed to start proxy (HTTP ${res.status})`);
Defensive patterns

Strategy: try-catch

Validate before calling

// check extras installed before attempting start
if (!headroomExtras.extras?.code && !headroomExtras.extras?.ml) {
  setHeadroomActionError("Install headroom extras first");
  return;
}

Try / catch

try {
  const res = await fetch("/api/headroom/start", { method: "POST" });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || `Failed to start proxy (HTTP ${res.status})`);
  await refreshHeadroomStatus();
} catch (e) {
  setHeadroomActionError(e.message);
}

Prevention

When it happens

Trigger: POST /api/headroom/start returns non-2xx: proxy binary/executable missing or not installed, port already in use, permission error spawning the process, or the server returns a bare status without a JSON error body (data.error undefined due to res.json() catch → {}).

Common situations: Another process already bound to the headroom proxy port; extras not installed before pressing start; executable lacks permission (chmod) or platform binary missing; server environment lacking required runtime.

Understand the failure class

Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.

Related errors


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