{"record":{"id":"870e55a9875aab9d","repo":"jackwener/OpenCLI","slug":"archive-snapshots-returned-malformed-cdx-payload-870e55","errorCode":null,"errorMessage":"archive snapshots returned malformed CDX payload: header row must be an array","messagePattern":"archive snapshots returned malformed CDX payload: header row must be an array","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/archive/snapshots.js","lineNumber":97,"sourceCode":"            throw new CommandExecutionError(`archive snapshots failed: HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        } catch (error) {\n            throw new CommandExecutionError(`archive snapshots returned malformed JSON: ${error?.message || error}`);\n        }\n\n        // CDX returns an array of arrays; the first row is the header.\n        if (!Array.isArray(data)) {\n            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');","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/archive/snapshots.js#L79-L115","documentation":"The CDX payload is an array-of-arrays with a header row, but the header row itself is not an array, so column names cannot be mapped to indexes. The library throws this because the CDX JSON contract requires `[[\"col1\",\"col2\",...], [row...], ...]`; anything else means the response shape changed or was substituted.","triggerScenarios":"The parsed JSON's first element is not an array — e.g. a flat array of objects, a plain string, or a numeric value returned instead of the expected `[header, ...rows]` structure; typically from an API change or a non-CDX JSON body.","commonSituations":"Wayback CDX API contract changes; hitting a different/mirror endpoint that returns object-per-row JSON; a gateway returning a compact JSON error array of strings.","solutions":["Inspect the raw payload with curl to confirm the header row shape.","Confirm the command targets the standard CDX endpoint (`http://web.archive.org/cdx/search/cdx`) and not a modified proxy URL.","Check for opencli updates that accommodate CDX response changes.","Report upstream if the CDX API contract changed for your query shape."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"const probe = await fetch('http://web.archive.org/cdx/search/cdx?url=example.com&output=json&limit=1');\nconst body = JSON.parse(await probe.text());\nif (!Array.isArray(body) || !Array.isArray(body[0])) console.warn('Unexpected CDX header shape');","typeGuard":"function hasArrayHeader(payload) {\n  return Array.isArray(payload) && payload.length > 0 && Array.isArray(payload[0]);\n}","tryCatchPattern":"try {\n  await exec('opencli archive snapshots example.com');\n} catch (e) {\n  if (String(e.message).includes('header row must be an array')) {\n    console.error('CDX contract changed — inspect raw payload and update tooling');\n  } else throw e;\n}","preventionTips":["Pin and update the opencli version deliberately","Smoke-test against CDX with curl after archive.org maintenance windows","Target the standard CDX endpoint, not modified proxies"],"tags":["json","schema","cdx-api","contract-change"],"backgroundTag":"unexpected-response-schema","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}