decolua/9router · warning
HTTP ${response.status}
Error message
HTTP ${response.status} What it means
syncModelCatalog fetches the remote model catalog with ETag-based caching. Any non-ok, non-304 HTTP response from the catalog server is rethrown as `HTTP <status>` after the fetch resolves.
Source
Thrown at src/lib/modelCatalog/sync.js:182
}
}
return entries;
}
// Run one sync. Returns a summary, or null when it could not complete.
export async function syncModelCatalog() {
if (state.running) return null;
state.running = true;
try {
const headers = { accept: "application/json" };
if (state.etag) headers["if-none-match"] = state.etag;
const response = await fetch(CATALOG_URL, { headers, signal: AbortSignal.timeout(FETCH_TIMEOUT_MS) });
let result;
if (response.status === 304) {
result = { status: "unchanged" };
} else if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
} else {
// ~23ms to parse, once a day, on a server that is otherwise idle at this
// point — not worth a worker thread.
const catalog = await response.json();
const etag = response.headers.get("etag") || null;
const entries = await collectEntries();
const { models, providers } = build(catalog, entries);
const serialized = JSON.stringify({ v: 1, etag, syncedAt: Date.now(), models, providers });
writeAtomic(CATALOG_FILE, serialized);
writeAtomic(CATALOG_RAW_FILE, JSON.stringify(slim(catalog)));
state.etag = etag;
invalidateCatalog();
result = {
status: "updated",
etag,
bytes: Buffer.byteLength(serialized),View on GitHub (pinned to 90b52e06ff)
Solutions
- Retry later — the sync is periodic and non-fatal; the app keeps working with the previously cached catalog.
- Check https://status or the catalog URL manually (curl -I $CATALOG_URL) to see whether the outage is server-side.
- If behind a proxy, fix proxy/firewall rules so the request reaches the real host.
- Update the app in case CATALOG_URL changed; as a last resort the catalog can be refreshed by a new sync once the server recovers.
Defensive patterns
Strategy: retry
Try / catch
for (let attempt = 0; attempt < 3; attempt++) {
try {
const r = await syncModelCatalog();
break;
} catch (err) {
if (/^HTTP \d+$/.test(err.message) && attempt < 2) {
await new Promise(r => setTimeout(r, 2 ** attempt * 1000)); // backoff, catalog sync is non-fatal
continue;
}
console.warn("model catalog sync failed, using cached catalog:", err.message);
}
} Prevention
- Treat catalog sync failures as non-fatal — the cached catalog keeps the app working.
- Check the status code in the message: 5xx/429 → retry later; 404 → CATALOG_URL changed, update the app.
- If behind a corporate proxy, verify the catalog host is reachable before assuming a server outage.
When it happens
Trigger: The catalog endpoint returns 4xx/5xx: 403/429 (rate limit or blocked), 404 (CATALOG_URL moved), 500/502/503 (server outage). 304 is handled as success (unchanged) and never reaches this throw.
Common situations: Catalog host temporarily down or behind a failing CDN; corporate proxy/firewall intercepting and returning an error page; hardcoded CATALOG_URL outdated after the project moved hosting; rate limiting from running many instances behind one IP.
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
- Failed to fetch image: ${res.status}
- Google translate fetch failed: ${res.status}
- Google TTS failed: ${res.status}
- MiniMax TTS error (${res.status})
- loadCodeAssist failed: HTTP ${response.status} ${errorText.s
AI-assisted analysis of decolua/9router@90b52e06ff (2026-08-30).
Data as JSON: /api/errors/a47c6b74750a2a93.
Report an issue: GitHub.