{"record":{"id":"70f973f14c02c0bf","repo":"odysseus-dev/odysseus","slug":"http-res-status-70f973","errorCode":null,"errorMessage":"HTTP ${res.status}","messagePattern":"HTTP \\$\\{res\\.status\\}","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"static/js/cookbook.js","lineNumber":2404,"sourceCode":"    }\n    async function _scanGgufRepo(rawValue) {\n      if (!dlGgufRow || !dlGgufQuant || !dlGgufNote) return false;\n      const rawRepo = _stripHfUrl(rawValue || '');\n      const ollamaName = _ollamaName(rawRepo);\n      const fileSplit = !ollamaName ? _splitRepoFile(rawRepo) : null;\n      const split = ollamaName ? { repo: ollamaName, include: null } : (fileSplit || _splitRepoTag(rawRepo));\n      const repo = split.repo || '';\n      if (ollamaName || split.include || !/^[^\\s/]+\\/[^\\s/]+$/.test(repo)) {\n        _hideGgufPicker();\n        return false;\n      }\n      dlGgufRow.style.display = 'flex';\n      dlGgufQuant.innerHTML = '<option value=\"\">Scanning...</option>';\n      dlGgufQuant.dataset.repo = repo;\n      dlGgufNote.textContent = '';\n      try {\n        const res = await fetch(`/api/cookbook/hf-gguf-files?repo_id=${encodeURIComponent(repo)}`, { credentials: 'same-origin' });\n        if (!res.ok) throw new Error(`HTTP ${res.status}`);\n        const data = await res.json();\n        if (!data.ok) throw new Error(data.error || 'scan failed');\n        if (dlGgufQuant.dataset.repo !== repo) return false;\n        const files = (data.files || [])\n          .map(s => String(s || ''))\n          .filter(name => /\\.gguf$/i.test(name));\n        const byQuant = new Map();\n        files.forEach(name => {\n          const quant = _ggufQuantFromPath(name);\n          if (!quant) return;\n          if (!byQuant.has(quant)) byQuant.set(quant, []);\n          byQuant.get(quant).push(name);\n        });\n        if (!byQuant.size) {\n          _hideGgufPicker('No GGUF quants found');\n          return false;\n        }\n        const quantRank = q => {","sourceCodeStart":2386,"sourceCodeEnd":2422,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/static/js/cookbook.js#L2386-L2422","documentation":"Error thrown when scanning a Hugging Face repo for GGUF files: GET /api/cookbook/hf-gguf-files?repo_id=... returned a non-OK status. Only the numeric status is reported. It fires before the data.ok application-level check (error 27).","triggerScenarios":"GET /api/cookbook/hf-gguf-files returns 422 (repo_id missing), 404 (route typo after backend update), 502/504 (proxy timeout while listing large repos), or 500 (backend exception calling the HF API).","commonSituations":"HF hub unreachable from the server (offline/proxy/rate limit surfacing as 500); repo id contains characters that break the query string (already encoded here, but custom deployments may double-decode); backend route renamed between versions; slow repo listing exceeding a gateway timeout.","solutions":["curl -i '/api/cookbook/hf-gguf-files?repo_id=<repo>' to see the status and body the UI discards","Verify outbound HTTPS to huggingface.co from the server host","Confirm the backend version still exposes this route (404 means route mismatch)","For 504, retry — large repos can be slow on first listing (HF API caching)"],"exampleFix":"// before\nif (!res.ok) throw new Error(`HTTP ${res.status}`);\n\n// after\nif (!res.ok) {\n  const body = await res.text().catch(() => '');\n  throw new Error(`HTTP ${res.status}: ${body.slice(0, 160)}`);\n}","handlingStrategy":"retry","validationCode":"if (!/^[^\\s/]+\\/[^\\s/]+$/.test(repo)) return false; // already guarded upstream — keep it","typeGuard":null,"tryCatchPattern":"try {\n  const res = await fetch(`/api/cookbook/hf-gguf-files?repo_id=${encodeURIComponent(repo)}`, { credentials: 'same-origin' });\n  if (!res.ok) {\n    if (res.status >= 500 || res.status === 429) { await new Promise(r => setTimeout(r, 1500)); return loadGgufPicker(rawRepo, fileSplit, true /*retried*/); }\n    const body = await res.text().catch(() => '');\n    throw new Error(`HTTP ${res.status}: ${body.slice(0, 160)}`);\n  }\n  const data = await res.json();\n  if (!data.ok) throw new Error(data.error || 'scan failed');\n  // ...\n} catch (e) {\n  dlGgufNote.textContent = e.message;\n  _hideGgufPicker();\n}","preventionTips":["Include the response body in the message — bare 'HTTP 502' is undiagnosable","Rate-limit scans per repo (debounce the repo input) to avoid HF 429s","Treat 5xx/429 as transient and offer one retry"],"tags":["fetch","http-error","huggingface","gguf","cookbook"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}