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

  1. 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.
  2. 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.
  3. 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.
  4. 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

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

Related errors


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