decolua/9router · warning · Error

extras status failed

Error message

extras status failed

What it means

TokenSaverClient's headroom status refresh throws this when GET /api/headroom/extras returns a non-OK response. It reports that the extras status (code/ml availability and version) could not be fetched; the thrown message is caught locally and shown via headroom state rather than crashing the page.

Source

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

        headers: { "Cache-Control": "no-store" },
      });
      const data = await res.json();
      setHeadroomStatus({ ...data, loading: false });
      if (!data?.installed) {
        setHeadroomExtras({
          version: null,
          extras: { code: false, ml: false },
          available: ["code", "ml"],
          loading: false,
        });
        setPendingExtras([]);
        return;
      }
      try {
        const er = await fetch("/api/headroom/extras", {
          headers: { "Cache-Control": "no-store" },
        });
        if (!er.ok) throw new Error("extras status failed");
        const ed = await er.json();
        setHeadroomExtras((s) => ({
          ...s,
          version: ed.version ?? null,
          extras: ed.extras || { code: false, ml: false },
          available: ed.available || ["code", "ml"],
          loading: false,
        }));
        setPendingExtras([]);
      } catch {
        setHeadroomExtras({
          version: null,
          extras: { code: false, ml: false },
          available: ["code", "ml"],
          loading: false,
        });
        setPendingExtras([]);
      }

View on GitHub (pinned to 90b52e06ff)

Solutions

  1. Check the response status/body of /api/headroom/extras in the network tab
  2. Install the headroom extras (use the card's install action → POST /api/headroom/extras) and retry
  3. Verify the server build includes the extras status route (version match between UI and server)
  4. Retry after confirming the gateway server is up and reachable

Example fix

// before
if (!er.ok) throw new Error("extras status failed");
// after
if (!er.ok) throw new Error(`extras status failed (HTTP ${er.status})`);
Defensive patterns

Strategy: try-catch

Validate before calling

// probe endpoint health before relying on status
const er = await fetch("/api/headroom/extras", { headers: { "Cache-Control": "no-store" } }).catch(() => null);
if (!er || !er.ok) setHeadroomExtras(s => ({ ...s, available: [], extras: { code: false, ml: false } }));

Try / catch

try {
  const er = await fetch("/api/headroom/extras");
  if (!er.ok) throw new Error(`extras status failed (HTTP ${er.status})`);
  const ed = await er.json();
  setHeadroomExtras(s => ({ ...s, ...ed }));
} catch (e) {
  setHeadroomExtras(s => ({ ...s, available: [], extras: { code: false, ml: false } }));
}

Prevention

When it happens

Trigger: GET /api/headroom/extras (with Cache-Control: no-store) returns 4xx/5xx: headroom extras backend not installed/running, endpoint removed or moved in a version change, or auth failure on the dashboard API.

Common situations: Extras module never installed so its status route errors; server running an older build without the /api/headroom/extras route; proxy/port misconfiguration making the dashboard API unreachable; transient server restart during polling.

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/ed7b0dda4edc4e2c. Report an issue: GitHub.