{"record":{"id":"45f0407d4f8ac65a","repo":"jackwener/OpenCLI","slug":"hf-models-returned-malformed-json-error-messag","errorCode":null,"errorMessage":"hf models returned malformed JSON: ${error?.message || error}","messagePattern":"hf models returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/hf/models.js","lineNumber":67,"sourceCode":"        let resp;\n        try {\n            resp = await fetch(url, {\n                headers: {\n                    'Accept': 'application/json',\n                    'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)',\n                },\n            });\n        } catch (error) {\n            throw new CommandExecutionError(`hf models request failed: ${error?.message || error}`);\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`hf models failed: HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        } catch (error) {\n            throw new CommandExecutionError(`hf models returned malformed JSON: ${error?.message || error}`);\n        }\n        const list = Array.isArray(data) ? data : [];\n        if (list.length === 0) {\n            throw new EmptyResultError('hf models', 'No matching models on huggingface.co.');\n        }\n        return list.slice(0, limit).map((m, i) => {\n            const id = m.id || m.modelId || '';\n            const slashIdx = id.indexOf('/');\n            const author = slashIdx > 0 ? id.slice(0, slashIdx) : '';\n            const tags = Array.isArray(m.tags) ? m.tags.filter(t => !t.startsWith('license:')).slice(0, 10).join(', ') : '';\n            return {\n                rank: i + 1,\n                id,\n                author,\n                pipelineTag: m.pipeline_tag || m.pipelineTag || '',\n                downloads: m.downloads ?? 0,\n                likes: m.likes ?? 0,\n                tags,","sourceCodeStart":49,"sourceCodeEnd":85,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/hf/models.js#L49-L85","documentation":"CommandExecutionError thrown at clis/hf/models.js:67 when the response body from https://huggingface.co/api/models has a 2xx status but resp.json() throws — the payload is not valid JSON. The library wraps the parse error so the original message (e.g. 'Unexpected token < in JSON') surfaces in the error text.","triggerScenarios":"The server responds 200 but with an HTML error/challenge page (e.g. an anti-bot or auth interstitial from a proxy/CDN), a truncated body from a dropped connection mid-response, or a body that is not JSON.","commonSituations":"Corporate SSL-inspection proxy injecting an HTML login page with status 200; captive portal hijacking the response; HF returning an HTML error page during an incident with 200; body truncation on flaky mobile networks.","solutions":["Inspect the raw response: curl -sS 'https://huggingface.co/api/models?limit=1' | head -c 200 — if you see HTML, a proxy or captive portal is intercepting.","Bypass/reconfigure the proxy or complete the portal login, then retry.","Retry on a stable network if the body was truncated mid-transfer.","If it reproduces while curl returns clean JSON, capture the failing response and report it — the CLI does not retry malformed responses internally."],"exampleFix":"// before\nconst out = JSON.parse(await (await fetch(url)).text()); // throws on HTML body\n// after\nconst text = await (await fetch(url)).text();\nif (text.trimStart().startsWith('<')) throw new Error('Got HTML instead of JSON — check proxy/captive portal');\nconst out = JSON.parse(text);","handlingStrategy":"try-catch","validationCode":"// Probe that the endpoint returns real JSON\nconst r = await fetch('https://huggingface.co/api/models?limit=1');\nconst text = await r.text();\nif (text.trimStart().startsWith('<')) {\n  console.error('Endpoint returned HTML (proxy/captive portal) — fix network before running hf models');\n}","typeGuard":"const isJsonObjectArray = (v) => Array.isArray(v) && v.every(x => x !== null && typeof x === 'object');","tryCatchPattern":"try {\n  await run('hf models');\n} catch (e) {\n  if (String(e.message).includes('returned malformed JSON')) {\n    console.error('Non-JSON response body — likely a proxy/portal HTML page or truncated body. Inspect with: curl -sS \"https://huggingface.co/api/models?limit=1\" | head');\n  } else throw e;\n}","preventionTips":["Bypass corporate SSL-inspection proxies or complete portal logins first.","Check that responses start with '[' not '<' when debugging.","Retry on stable networks to rule out truncated bodies.","Compare CLI failures against curl output to isolate interception."],"tags":["json","parsing","network","huggingface"],"backgroundTag":"malformed-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}