jackwener/OpenCLI · error · CommandExecutionError

hf datasets returned malformed JSON: ${error?.message || err

Error message

hf datasets returned malformed JSON: ${error?.message || error}

What it means

The datasets API response body could not be parsed as JSON (resp.json() threw), so the command throws CommandExecutionError with the parse error message. This usually means the endpoint returned HTML (error page, login/redirect page) instead of JSON.

Source

Thrown at clis/hf/datasets.js:65

        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 datasets request failed: ${error?.message || error}`);
        }
        if (!resp.ok) {
            throw new CommandExecutionError(`hf datasets failed: HTTP ${resp.status}`);
        }
        let data;
        try {
            data = await resp.json();
        } catch (error) {
            throw new CommandExecutionError(`hf datasets returned malformed JSON: ${error?.message || error}`);
        }
        const list = Array.isArray(data) ? data : [];
        if (list.length === 0) {
            throw new EmptyResultError('hf datasets', 'No matching datasets on huggingface.co.');
        }
        return list.slice(0, limit).map((d, i) => {
            const id = d.id || '';
            const slashIdx = id.indexOf('/');
            const author = slashIdx > 0 ? id.slice(0, slashIdx) : '';
            const tags = Array.isArray(d.tags) ? d.tags.filter(t => !t.startsWith('license:')).slice(0, 10).join(', ') : '';
            return {
                rank: i + 1,
                id,
                author,
                downloads: d.downloads ?? 0,
                likes: d.likes ?? 0,
                tags,
                lastModified: d.lastModified ? String(d.lastModified).slice(0, 10) : '',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the raw response body (curl the same URL) to see what was actually returned
  2. Bypass or correctly configure proxies that rewrite responses
  3. Retry if the response was truncated; check Accept: application/json header is sent
  4. Update the CLI if HF changed the endpoint's content type

Example fix

// before
data = await resp.json(); // throws on HTML
// after
const text = await resp.text(); try { data = JSON.parse(text); } catch (e) { console.error('non-JSON body:', text.slice(0, 200)); }
Defensive patterns

Strategy: fallback

Validate before calling

const pre = await fetch(url, { headers: { Accept: 'application/json' } }); const ct = pre.headers.get('content-type') || ''; if (!ct.includes('application/json')) throw new Error(`expected JSON, got ${ct}`);

Type guard

function isDatasetArray(v) { return Array.isArray(v) && v.every(d => d && typeof d.id === 'string'); }

Try / catch

try { await hfDatasets(args); } catch (e) { if (String(e.message).includes('malformed JSON')) { console.error('non-JSON body from HF (proxy/HTML page?); bypass proxy or retry'); return null; } throw e; }

Prevention

When it happens

Trigger: resp.json() rejects: HF returned an HTML error/interstitial page, empty body, or truncated response due to proxy/gateway interference.

Common situations: Captive portal or proxy returning HTML; HF serving a 200 HTML maintenance page; content-encoding mismatch; network truncation.

Understand the failure class

Background: "Invalid JSON response" and "Failed to parse response" errors: when an API answers 200 but the body isn't the JSON your library expected — this error's family across 28 libraries.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/29e8c2f85d353628. Report an issue: GitHub.