decolua/9router · warning · Error
Failed to update quota visibility
Error message
Failed to update quota visibility
What it means
ProviderLimits persists per-provider quota visibility (hidden rows) by PATCHing /api/settings with { quotaVisibility }. On any non-OK response it throws 'Failed to update quota visibility', logs the error, and rolls the local visibility state back to previousVisibility. Note the thrown message is fixed — the actual HTTP status is only visible in the console.error.
Source
Thrown at src/app/(dashboard)/dashboard/usage/components/ProviderLimits/index.js:584
await fetch("/api/settings", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ [settingsKey]: cfg }),
});
} catch {
setAutoPingMaps(previous);
}
}, [autoPingMaps]);
const updateQuotaVisibility = useCallback(async (nextVisibility, previousVisibility) => {
setQuotaVisibility(nextVisibility);
try {
const response = await fetch("/api/settings", {
method: "PATCH",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({ quotaVisibility: nextVisibility }),
});
if (!response.ok) throw new Error("Failed to update quota visibility");
} catch (error) {
console.error("Error updating quota visibility:", error);
setQuotaVisibility(previousVisibility);
}
}, []);
const handleHideQuota = useCallback((provider, quota) => {
const key = getQuotaVisibilityKey(quota);
if (!provider || !key) return;
const previous = quotaVisibility;
const providerVisibility = previous[provider] || {};
const hidden = new Set(providerVisibility.hidden || []);
hidden.add(key);
const next = {
...previous,
[provider]: {
...providerVisibility,View on GitHub (pinned to 90b52e06ff)
Solutions
- Log back into the dashboard — 401 from /api/settings means the session cookie is no longer valid.
- Check server logs for settings-save failures and ensure the data directory (~/.9router or DATA_DIR) is writable.
- Retry the toggle; the UI already reverts the optimistic change, so a retry after re-login is safe.
- Include response.status in the thrown message so failures are diagnosable without the console.
Example fix
// before
if (!response.ok) throw new Error("Failed to update quota visibility");
// after
if (!response.ok) throw new Error(`Failed to update quota visibility (HTTP ${response.status})`); Defensive patterns
Strategy: try-catch
Validate before calling
const sessionOk = await fetch("/api/settings", { method: "GET" }).then((r) => r.ok).catch(() => false);
if (!sessionOk) { redirectToLogin(); return; }
const isValidVisibility = (v) => v && typeof v === "object" && Object.values(v).every((b) => typeof b === "boolean"); Type guard
const isVisibilityMap = (v) => v !== null && typeof v === "object" && !Array.isArray(v) && Object.values(v).every((x) => typeof x === "boolean");
Try / catch
const previousVisibility = quotaVisibility;
setQuotaVisibility(nextVisibility);
try {
const response = await fetch("/api/settings", { method: "PATCH", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ quotaVisibility: nextVisibility }) });
if (response.status === 401) { redirectToLogin(); return; }
if (!response.ok) throw new Error(`Failed to update quota visibility (HTTP ${response.status})`);
} catch (error) {
console.error("Error updating quota visibility:", error);
setQuotaVisibility(previousVisibility);
} Prevention
- Always keep the previous value to roll back the optimistic update (the code already does this).
- Re-authenticate on 401 rather than silently reverting.
- Verify the settings DB is writable when PATCHes repeatedly fail.
When it happens
Trigger: PATCH /api/settings with body { quotaVisibility: nextVisibility } returns non-OK — most commonly 401 when the dashboard session expired, 400 on body validation, or 500 when persisting settings to the SQLite store fails — inside the visibility toggle handler at ProviderLimits/index.js:584.
Common situations: Dashboard session expired mid-use (JWT_SECRET rotated or cookie expired); settings DB write failure (read-only data dir, disk full); server restarting while the toggle is clicked.
Related errors
- Failed to fetch connections
- [${res.status}] ${text}
- Upstream error (${res.status})
- Edge TTS voices fetch failed: ${res.status}
- ElevenLabs API key required
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/323e9d79bbbb18b6.
Report an issue: GitHub.