jackwener/OpenCLI · error · CommandExecutionError
archive snapshots returned malformed CDX payload: top-level
Error message
archive snapshots returned malformed CDX payload: top-level payload must be an array
What it means
After successfully parsing the CDX response as JSON, the library verifies the CDX contract: a JSON array of arrays whose first row is the column header. This error is thrown when the parsed body is valid JSON but not a top-level array (e.g. an object with an error field, or a different shape entirely).
Source
Thrown at clis/archive/snapshots.js:90
'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)',
},
});
} catch (error) {
throw new CommandExecutionError(`archive snapshots request failed: ${error?.message || error}`);
}
if (!resp.ok) {
throw new CommandExecutionError(`archive snapshots failed: HTTP ${resp.status}`);
}
let data;
try {
data = await resp.json();
} catch (error) {
throw new CommandExecutionError(`archive snapshots returned malformed JSON: ${error?.message || error}`);
}
// CDX returns an array of arrays; the first row is the header.
if (!Array.isArray(data)) {
throw new CommandExecutionError('archive snapshots returned malformed CDX payload: top-level payload must be an array');
}
if (data.length < 2) {
throw new EmptyResultError('archive snapshots', `No Wayback snapshots for "${target}".`);
}
const [header, ...rows] = data;
if (!Array.isArray(header)) {
throw new CommandExecutionError('archive snapshots returned malformed CDX payload: header row must be an array');
}
const cols = {};
header.forEach((name, i) => { cols[name] = i; });
const timestampCol = requireCdxColumn(cols, 'timestamp');
const originalCol = requireCdxColumn(cols, 'original');
const statusCol = requireCdxColumn(cols, 'statuscode');
const mimetypeCol = requireCdxColumn(cols, 'mimetype');
return rows.slice(0, limit).map(row => {
if (!Array.isArray(row)) {
throw new CommandExecutionError('archive snapshots returned malformed CDX payload: snapshot row must be an array');View on GitHub (pinned to 49907e53dc)
Solutions
- Print/inspect the raw response body (`curl 'http://web.archive.org/cdx/search/cdx?url=YOUR_URL&output=json&limit=2'`) to see the actual payload shape.
- Check that the target URL argument is a plain URL/path — overly long or odd query strings can push CDX into an error-object response.
- Verify the CDX API is healthy (status.archive.org) and whether the response contract changed; update the opencli package if a newer version adapts to it.
- Retry later if the API is temporarily serving error objects.
Example fix
// before: ambiguous URL with query string
await exec('opencli archive snapshots "example.com/page?utm=x&a=1"');
// after: strip tracking query params so CDX returns normal rows
await exec('opencli archive snapshots example.com/page'); Defensive patterns
Strategy: type-guard
Validate before calling
// Validate the expected CDX envelope after receiving raw JSON elsewhere
function looksLikeCdx(v) { return Array.isArray(v); } Type guard
function isCdxPayload(v) {
return Array.isArray(v) && v.length >= 1 && Array.isArray(v[0]);
} Try / catch
try {
await exec('opencli archive snapshots example.com');
} catch (e) {
if (String(e.message).includes('top-level payload must be an array')) {
console.error('CDX response shape changed or an error object was returned; inspect raw payload');
} else throw e;
} Prevention
- Keep the target URL simple (strip tracking query params)
- Watch archive.org API announcements for CDX contract changes
- Keep the opencli package updated
- Inspect raw CDX output when upgrading tooling
When it happens
Trigger: The CDX API returned valid JSON that is not an array — for example `{"error": ...}` for blocked/invalid requests that still return HTTP 200, a changed API response shape, or an intermediary (proxy/gateway) returning its own JSON error object with status 200.
Common situations: Wayback CDX deprecations or API changes altering the response envelope; transparent proxies returning JSON-formatted error pages; calling an unofficial CDX mirror with a different response shape; URL query strings causing the API to return an error object instead of rows.
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 snapshots returned malformed CDX payload: header row
- archive snapshots returned malformed CDX payload: snapshot r
- archive snapshots returned malformed CDX payload: snapshot r
- archive snapshots returned malformed CDX payload: snapshot r
- 12306 ${endpoint} returned an unexpected payload shape
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/2e80900f0349b775.
Report an issue: GitHub.