jackwener/OpenCLI · error · CommandExecutionError
wikipedia returned malformed JSON: ${error?.message || error
Error message
wikipedia returned malformed JSON: ${error?.message || error} What it means
After a 2xx response, page.js parses the body with resp.json(). If parsing fails — the body is not valid JSON (HTML error/interstitial page, truncated stream, wrong content type) — it throws a CommandExecutionError with the parse error message.
Source
Thrown at clis/wikipedia/page.js:69
let resp;
try {
resp = await fetch(url, {
headers: {
'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)',
'Accept': 'application/json',
},
});
} catch (error) {
throw new CommandExecutionError(`wikipedia page request failed: ${error?.message || error}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`wikipedia page failed: HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
} catch (error) {
throw new CommandExecutionError(`wikipedia returned malformed JSON: ${error?.message || error}`);
}
if (data?.error) {
throw new CommandExecutionError(`wikipedia API error: ${data.error.info || data.error.code}`);
}
const pages = Array.isArray(data?.query?.pages) ? data.query.pages : [];
const page = pages[0];
if (!page || page.missing) {
throw new EmptyResultError('wikipedia page', `No article "${title}" on ${lang}.wikipedia.org. Try \`opencli wikipedia search\` first.`);
}
const fullExtract = String(page.extract ?? '');
if (!fullExtract.trim()) {
throw new EmptyResultError('wikipedia page', `Article "${page.title}" exists but has no plain-text extract (likely a disambiguation/redirect page).`);
}
const allParas = fullExtract.split(/\n{2,}/).map(s => s.trim()).filter(Boolean);
const paras = paragraphsCap > 0 ? allParas.slice(0, paragraphsCap) : allParas;
return [{
title: page.title,View on GitHub (pinned to 49907e53dc)
Solutions
- Capture and inspect the raw response text to see what was actually returned
- Retry — truncation is often transient
- Bypass proxies/VPNs or fix captive-portal connectivity
- Confirm the request targets <lang>.wikipedia.org/w/api.php with format=json
Example fix
// before
const data = await resp.json();
// after
const text = await resp.text();
let data;
try { data = JSON.parse(text); }
catch { throw new Error(`unexpected body: ${text.slice(0, 200)}`); } Defensive patterns
Strategy: try-catch
Type guard
function looksLikeApiJson(v) { return v !== null && typeof v === 'object' && ('query' in v || 'error' in v); } Try / catch
try {
return await pageCommand(args);
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('malformed JSON')) {
console.error('non-JSON body from wikipedia — likely proxy/interstitial; retry');
throw err;
}
throw err;
} Prevention
- Bypass proxies/captive portals when calling the API
- Retry transient truncations
- Verify api.php + format=json is requested (the CLI already does this)
- Check the raw body when errors persist to spot injected HTML
When it happens
Trigger: A proxy, captive portal, or anti-bot layer returning an HTML page with status 200; the response stream being cut off mid-body; hitting a non-API URL that serves HTML while still reporting success.
Common situations: Corporate networks or hotel Wi-Fi injecting login pages; aggressive caching middleboxes serving stale HTML; malformed responses during partial Wikimedia incidents.
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
- Chess.com callback returned malformed JSON for ${url}: ${err
- mdn search returned malformed JSON: ${err?.message ?? err}
- ${label} returned malformed JSON: ${err?.message ?? err}
- Malformed JSON from Stack Exchange API for ${label}: ${detai
- ${label} returned malformed JSON: ${err?.message ?? err}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/3f29e5ecded948dc.
Report an issue: GitHub.