decolua/9router · error · Error
Install failed
Error message
Install failed
What it means
The extras install handler throws this when POST /api/headroom/extras with {extras: pendingExtras} responds non-2xx without a specific `error` field. It means the optional headroom extras (code/ml) failed to install; the message is shown via headroomActionError.
Source
Thrown at src/app/(dashboard)/dashboard/token-saver/TokenSaverClient.js:254
logPollRef.current = null;
}
}, []);
useEffect(() => () => stopLogPolling(), [stopLogPolling]);
const installExtrasConfirmed = useCallback(async () => {
if (pendingExtras.length === 0) return;
setExtrasActionLoading(true);
setExtrasActionError("");
startLogPolling();
try {
const res = await fetch("/api/headroom/extras", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ extras: pendingExtras }),
});
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data.error || "Install failed");
setHeadroomExtras((s) => ({
...s,
version: data.version ?? s.version,
extras: data.extras || s.extras,
}));
setPendingExtras([]);
} catch (e) {
setExtrasActionError(e.message);
} finally {
stopLogPolling();
setExtrasActionLoading(false);
}
}, [pendingExtras, startLogPolling, stopLogPolling]);
const removeExtraConfirmed = useCallback(async (extra) => {
setRemovingExtra(extra);
setExtrasActionError("");
startLogPolling();View on GitHub (pinned to 90b52e06ff)
Solutions
- Inspect the POST response status/body for the server's real install error
- Verify network access to the package registry from the server host
- Check the extras install directory permissions and free disk space
- Confirm the requested extras names (code/ml) are supported on this platform/server version
Example fix
// before
if (!res.ok) throw new Error(data.error || "Install failed");
// after
if (!res.ok) throw new Error(data.error || `Install failed (HTTP ${res.status})`); Defensive patterns
Strategy: try-catch
Validate before calling
// only request known extras const allowed = ["code", "ml"]; const extras = pendingExtras.filter(x => allowed.includes(x)); if (!extras.length) return;
Type guard
const isKnownExtra = (x) => x === "code" || x === "ml";
Try / catch
try {
const res = await fetch("/api/headroom/extras", { method: "POST", body: JSON.stringify({ extras: pendingExtras }) });
const data = await res.json().catch(() => ({}));
if (!res.ok) throw new Error(data.error || `Install failed (HTTP ${res.status})`);
setPendingExtras([]);
} catch (e) {
setHeadroomActionError(e.message);
} Prevention
- Verify network/registry access from the server before installing
- Check disk space and write permissions on the extras directory
- Only install extras supported by the current platform build
- Read the server response body to distinguish download vs permission failures
When it happens
Trigger: POST /api/headroom/extras returns non-2xx: package download fails (no network/registry unreachable), install script lacks permission, unsupported platform/binary unavailable, or response body is not JSON (res.json() catch → {} so data.error is undefined).
Common situations: Offline or corporate proxy blocking the package registry; installing on a platform without prebuilt binaries; disk full or permission denied writing to the extras directory; requesting extras names the server doesn't recognize.
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
- extras status failed
- Failed to save mappings
- Failed to toggle DNS
- Failed to start proxy
- Failed to fetch image: ${res.status}
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/f827311a7f41ac86.
Report an issue: GitHub.