decolua/9router · error · Error

Remove failed

Error message

Remove failed

What it means

TokenSaverClient removes a Headroom compression extra by DELETEing to /api/headroom/extras. When the route responds with a non-OK status it returns { error, code } — e.g. NO_PYTHON (no Python 3.10 found), INVALID_EXTRAS, or a generic 500 from pip uninstall failing — and the client falls back to the literal 'Remove failed' message when data.error is absent. It signals the uninstall of the extra did not complete server-side.

Source

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

      setExtrasActionError(e.message);
    } finally {
      stopLogPolling();
      setExtrasActionLoading(false);
    }
  }, [pendingExtras, startLogPolling, stopLogPolling]);

  const removeExtraConfirmed = useCallback(async (extra) => {
    setRemovingExtra(extra);
    setExtrasActionError("");
    startLogPolling();
    try {
      const res = await fetch("/api/headroom/extras", {
        method: "DELETE",
        headers: { "Content-Type": "application/json" },
        body: JSON.stringify({ extras: [extra] }),
      });
      const data = await res.json().catch(() => ({}));
      if (!res.ok) throw new Error(data.error || "Remove failed");
      setHeadroomExtras((s) => ({
        ...s,
        version: data.version ?? s.version,
        extras: data.extras || s.extras,
      }));
    } catch (e) {
      setExtrasActionError(e.message);
    } finally {
      stopLogPolling();
      setRemovingExtra(null);
    }
  }, [startLogPolling, stopLogPolling]);

  const handleInstallExtras = useCallback(() => {
    if (pendingExtras.length === 0) return;
    // Warn about the heavy ~1GB torch download before installing [ml].
    if (pendingExtras.includes("ml")) {
      setExtrasConfirm({

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Check that a Python 3.10 interpreter is installed and discoverable (the route requires findPython310() to succeed).
  2. Reload the extras list and confirm the extra is actually still installed before retrying the remove.
  3. Read the install log via GET /api/headroom/extras?log=1 to see the pip uninstall failure reason.
  4. Retry the DELETE; transient pip/network failures during uninstall can resolve on a second attempt.

Example fix

// before
if (!res.ok) throw new Error(data.error || "Remove failed");
// after
if (!res.ok) throw new Error(data.error ? `${data.error}${data.code ? ` (${data.code})` : ""}` : `Remove failed (HTTP ${res.status})`);
Defensive patterns

Strategy: try-catch

Validate before calling

if (!Array.isArray(extras) || extras.some((e) => typeof e !== "string" || !e.trim())) throw new Error("extras must be non-empty strings");
const status = await fetch("/api/headroom/extras").then((r) => r.json()).catch(() => null);
if (!status?.pythonAvailable) throw new Error("Python 3.10 not found — remove requires a Python interpreter");

Type guard

const isApiError = (d) => d && typeof d === "object" && typeof d.error === "string";

Try / catch

try {
  const res = await fetch("/api/headroom/extras", { method: "DELETE", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ extras: [extra] }) });
  const data = await res.json().catch(() => ({}));
  if (!res.ok) throw new Error(data.error || `Remove failed (HTTP ${res.status})`);
} catch (e) {
  console.warn("headroom extra remove failed:", e.message);
  await refreshExtras();
}

Prevention

When it happens

Trigger: DELETE /api/headroom/extras with body { extras: [name] } returns 400 when uninstallHeadroomExtras throws NO_PYTHON or INVALID_EXTRAS, or 500 when the pip uninstall subprocess fails; the dashboard then throws this error in the catch block at TokenSaverClient.js:280.

Common situations: No suitable Python 3.10 interpreter on the machine; typo'd or already-uninstalled extra name; pip uninstall permission errors; server not running so fetch fails and data defaults to {}.

Related errors


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