jackwener/OpenCLI · error · CommandExecutionError

archive snapshots returned malformed CDX payload: snapshot r

Error message

archive snapshots returned malformed CDX payload: snapshot row must be an array

What it means

Individual data rows in the CDX array-of-arrays payload must each be arrays aligned with the header. This error is thrown when a row after the header is not an array (e.g. a null, object, or string), so its cells cannot be read by column index.

Source

Thrown at clis/archive/snapshots.js:108

            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');
            }
            const timestamp = String(row[timestampCol] ?? '');
            const original = String(row[originalCol] ?? '');
            const status = row[statusCol];
            const mimetype = row[mimetypeCol];
            if (!/^\d{14}$/.test(timestamp) || !original) {
                throw new CommandExecutionError('archive snapshots returned malformed CDX payload: snapshot row is missing timestamp/original URL');
            }
            if (status == null || mimetype == null || String(status) === '' || String(mimetype) === '') {
                throw new CommandExecutionError('archive snapshots returned malformed CDX payload: snapshot row is missing statuscode/mimetype');
            }
            return {
                timestamp,
                snapshot_url: buildWaybackUrl(timestamp, original),
                status: String(status),
                mimetype: String(mimetype),
                original_url: original,
            };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-run the command — null/tombstone rows can be transient in CDX output.
  2. Inspect the raw payload with curl and note which rows are non-arrays.
  3. Add a `filter` or narrower `from`/`to` range to skip the problematic captures (e.g. query a specific path rather than the whole domain).
  4. Check CDX API status / opencli updates if it reproduces consistently.

Example fix

// before: domain-wide query hitting tombstone rows
await exec('opencli archive snapshots example.com --limit 1000');
// after: narrower, filtered query
await exec('opencli archive snapshots example.com/index.html --limit 20');
Defensive patterns

Strategy: validation

Validate before calling

// Sanity-check a raw CDX row set before relying on the CLI
const rows = payload.slice(1);
if (rows.some(r => !Array.isArray(r))) console.warn('CDX payload contains non-array rows');

Type guard

function allRowsAreArrays(payload) {
  return Array.isArray(payload) && payload.slice(1).every(r => Array.isArray(r));
}

Try / catch

try {
  await exec('opencli archive snapshots example.com/index.html --limit 20');
} catch (e) {
  if (String(e.message).includes('snapshot row must be an array')) {
    // skip malformed captures: retry with a narrower path/range
  } else throw e;
}

Prevention

When it happens

Trigger: The CDX API returned a payload where at least one record after the header is a non-array value — commonly `null` entries for blocked/tombstoned captures or an API response-shape change mixing rows with placeholder values.

Common situations: Very old or collapsed captures producing null rows in CDX output; responses assembled by intermediary proxies; API changes introducing per-row objects.

Understand the failure class

Related errors


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