{"record":{"id":"a8aae13148a88dda","repo":"jackwener/OpenCLI","slug":"archive-snapshots-returned-malformed-cdx-payload-a8aae1","errorCode":null,"errorMessage":"archive snapshots returned malformed CDX payload: snapshot row must be an array","messagePattern":"archive snapshots returned malformed CDX payload: snapshot row must be an array","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/archive/snapshots.js","lineNumber":108,"sourceCode":"            throw new CommandExecutionError('archive snapshots returned malformed CDX payload: top-level payload must be an array');\n        }\n        if (data.length < 2) {\n            throw new EmptyResultError('archive snapshots', `No Wayback snapshots for \"${target}\".`);\n        }\n        const [header, ...rows] = data;\n        if (!Array.isArray(header)) {\n            throw new CommandExecutionError('archive snapshots returned malformed CDX payload: header row must be an array');\n        }\n        const cols = {};\n        header.forEach((name, i) => { cols[name] = i; });\n        const timestampCol = requireCdxColumn(cols, 'timestamp');\n        const originalCol = requireCdxColumn(cols, 'original');\n        const statusCol = requireCdxColumn(cols, 'statuscode');\n        const mimetypeCol = requireCdxColumn(cols, 'mimetype');\n\n        return rows.slice(0, limit).map(row => {\n            if (!Array.isArray(row)) {\n                throw new CommandExecutionError('archive snapshots returned malformed CDX payload: snapshot row must be an array');\n            }\n            const timestamp = String(row[timestampCol] ?? '');\n            const original = String(row[originalCol] ?? '');\n            const status = row[statusCol];\n            const mimetype = row[mimetypeCol];\n            if (!/^\\d{14}$/.test(timestamp) || !original) {\n                throw new CommandExecutionError('archive snapshots returned malformed CDX payload: snapshot row is missing timestamp/original URL');\n            }\n            if (status == null || mimetype == null || String(status) === '' || String(mimetype) === '') {\n                throw new CommandExecutionError('archive snapshots returned malformed CDX payload: snapshot row is missing statuscode/mimetype');\n            }\n            return {\n                timestamp,\n                snapshot_url: buildWaybackUrl(timestamp, original),\n                status: String(status),\n                mimetype: String(mimetype),\n                original_url: original,\n            };","sourceCodeStart":90,"sourceCodeEnd":126,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/archive/snapshots.js#L90-L126","documentation":"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.","triggerScenarios":"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.","commonSituations":"Very old or collapsed captures producing null rows in CDX output; responses assembled by intermediary proxies; API changes introducing per-row objects.","solutions":["Re-run the command — null/tombstone rows can be transient in CDX output.","Inspect the raw payload with curl and note which rows are non-arrays.","Add a `filter` or narrower `from`/`to` range to skip the problematic captures (e.g. query a specific path rather than the whole domain).","Check CDX API status / opencli updates if it reproduces consistently."],"exampleFix":"// before: domain-wide query hitting tombstone rows\nawait exec('opencli archive snapshots example.com --limit 1000');\n// after: narrower, filtered query\nawait exec('opencli archive snapshots example.com/index.html --limit 20');","handlingStrategy":"validation","validationCode":"// Sanity-check a raw CDX row set before relying on the CLI\nconst rows = payload.slice(1);\nif (rows.some(r => !Array.isArray(r))) console.warn('CDX payload contains non-array rows');","typeGuard":"function allRowsAreArrays(payload) {\n  return Array.isArray(payload) && payload.slice(1).every(r => Array.isArray(r));\n}","tryCatchPattern":"try {\n  await exec('opencli archive snapshots example.com/index.html --limit 20');\n} catch (e) {\n  if (String(e.message).includes('snapshot row must be an array')) {\n    // skip malformed captures: retry with a narrower path/range\n  } else throw e;\n}","preventionTips":["Query specific paths instead of whole domains to avoid tombstone rows","Use smaller limits and time ranges","Retry once — tombstone rows are often transient","Inspect raw CDX output for the failing row"],"tags":["json","schema","cdx-api","row-validation"],"backgroundTag":"unexpected-response-schema","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}