jackwener/OpenCLI · error · CommandExecutionError
hf models returned malformed JSON: ${error?.message || error
Error message
hf models returned malformed JSON: ${error?.message || error} What it means
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.
Source
Thrown at clis/hf/models.js:67
let resp;
try {
resp = await fetch(url, {
headers: {
'Accept': 'application/json',
'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)',
},
});
} catch (error) {
throw new CommandExecutionError(`hf models request failed: ${error?.message || error}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`hf models failed: HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
} catch (error) {
throw new CommandExecutionError(`hf models returned malformed JSON: ${error?.message || error}`);
}
const list = Array.isArray(data) ? data : [];
if (list.length === 0) {
throw new EmptyResultError('hf models', 'No matching models on huggingface.co.');
}
return list.slice(0, limit).map((m, i) => {
const id = m.id || m.modelId || '';
const slashIdx = id.indexOf('/');
const author = slashIdx > 0 ? id.slice(0, slashIdx) : '';
const tags = Array.isArray(m.tags) ? m.tags.filter(t => !t.startsWith('license:')).slice(0, 10).join(', ') : '';
return {
rank: i + 1,
id,
author,
pipelineTag: m.pipeline_tag || m.pipelineTag || '',
downloads: m.downloads ?? 0,
likes: m.likes ?? 0,
tags,View on GitHub (pinned to 49907e53dc)
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.
Example fix
// before
const out = JSON.parse(await (await fetch(url)).text()); // throws on HTML body
// after
const text = await (await fetch(url)).text();
if (text.trimStart().startsWith('<')) throw new Error('Got HTML instead of JSON — check proxy/captive portal');
const out = JSON.parse(text); Defensive patterns
Strategy: try-catch
Validate before calling
// Probe that the endpoint returns real JSON
const r = await fetch('https://huggingface.co/api/models?limit=1');
const text = await r.text();
if (text.trimStart().startsWith('<')) {
console.error('Endpoint returned HTML (proxy/captive portal) — fix network before running hf models');
} Type guard
const isJsonObjectArray = (v) => Array.isArray(v) && v.every(x => x !== null && typeof x === 'object');
Try / catch
try {
await run('hf models');
} catch (e) {
if (String(e.message).includes('returned malformed JSON')) {
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');
} else throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- archive search returned malformed JSON: ${error?.message ||
- archive wayback returned malformed JSON: ${error?.message ||
- ${label} returned malformed JSON: ${err?.message ?? err}
- hf datasets returned malformed JSON: ${error?.message || err
- hf spaces returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/45f0407d4f8ac65a.
Report an issue: GitHub.