jackwener/OpenCLI · error · CommandExecutionError
archive search returned malformed JSON: ${error?.message ||
Error message
archive search returned malformed JSON: ${error?.message || error} What it means
This CommandExecutionError is thrown when the HTTP response from archive.org's advancedsearch endpoint has ok status but its body cannot be parsed as JSON (resp.json() rejects). The parse error message is interpolated. It means the body was HTML, empty, or truncated rather than valid JSON.
Source
Thrown at clis/archive/search.js:82
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(`archive search request failed: ${error?.message || error}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`archive search failed: HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
} catch (error) {
throw new CommandExecutionError(`archive search returned malformed JSON: ${error?.message || error}`);
}
const docs = data?.response?.docs;
if (!Array.isArray(docs)) {
throw new CommandExecutionError('archive search returned malformed payload: response.docs must be an array');
}
if (docs.length === 0) {
throw new EmptyResultError('archive search', `No items match "${query}" on archive.org.`);
}
return docs.slice(0, limit).map((d, i) => {
const id = String(d.identifier ?? '');
if (!IDENTIFIER_RE.test(id)) {
throw new CommandExecutionError('archive search returned malformed payload: result row is missing a stable identifier');
}
const downloads = Number(d.downloads ?? 0);
if (!Number.isFinite(downloads)) {
throw new CommandExecutionError(`archive search returned malformed payload for "${id}": downloads must be numeric`);View on GitHub (pinned to 49907e53dc)
Solutions
- Check what the endpoint actually returns: `curl -s 'https://archive.org/advancedsearch.php?q=test&output=json' | head`
- Disable/bypass intercepting proxies or complete captive-portal login, then retry
- Retry — truncated bodies are often transient
- Catch this error and treat it as a network-layer failure with backoff, not a data problem
Example fix
// before
const data = JSON.parse(body); // throws raw SyntaxError on HTML body
// after
let data;
try {
data = JSON.parse(body);
} catch (err) {
throw new Error(`archive search returned malformed JSON: ${err.message}`);
} Defensive patterns
Strategy: try-catch
Validate before calling
// pre-check the endpoint returns JSON in your environment
const probe = await fetch('https://archive.org/advancedsearch.php?q=test&output=json');
const ct = probe.headers.get('content-type') || '';
if (!ct.includes('json')) throw new Error('endpoint not returning JSON; check proxy/captive portal'); Type guard
const isJsonObject = (text) => { try { return typeof JSON.parse(text) === 'object'; } catch { return false; } }; Try / catch
try {
rows = await run(['archive', 'search', query]);
} catch (err) {
if (err instanceof CommandExecutionError && err.message.includes('malformed JSON')) {
// treat as network-layer failure: retry with backoff or surface clearly
await new Promise(r => setTimeout(r, 1000));
rows = await run(['archive', 'search', query]);
} else { throw err; }
} Prevention
- Complete captive-portal login before running batch searches
- Bypass or configure SSL-inspection proxies for archive.org
- Fetch the endpoint once with curl to verify JSON content-type in your environment
- Treat 200-with-HTML as a network environment problem, not a data problem
When it happens
Trigger: Calling `opencli archive search ...` when a captive portal or proxy returns an HTML login/block page with 200; archive.org serves an error page with 200; the response body is cut off mid-stream; a misbehaving middlebox rewrites content.
Common situations: Hotel/airport wifi captive portals intercepting the request; corporate SSL-inspection proxies injecting pages; extremely large responses truncated by an intermediary; archive.org returning an HTML rate-limit notice with 200.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- archive search request failed: ${error?.message || error}
- archive wayback returned malformed JSON: ${error?.message ||
- ${label} returned malformed JSON: ${err?.message ?? err}
- `${label} returned malformed JSON: ${err?.message ?? err}`
- hf models returned malformed JSON: ${error?.message || error
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4ec33b94fa8034e4.
Report an issue: GitHub.