{"record":{"id":"cf0ee5c82377eb7a","repo":"jackwener/OpenCLI","slug":"archive-wayback-returned-malformed-json-error","errorCode":null,"errorMessage":"archive wayback returned malformed JSON: ${error?.message || error}","messagePattern":"archive wayback returned malformed JSON: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/archive/wayback.js","lineNumber":64,"sourceCode":"        let resp;\n        try {\n            resp = await fetch(apiUrl, {\n                headers: {\n                    'Accept': 'application/json',\n                    'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)',\n                },\n            });\n        } catch (error) {\n            throw new CommandExecutionError(`archive wayback request failed: ${error?.message || error}`);\n        }\n        if (!resp.ok) {\n            throw new CommandExecutionError(`archive wayback failed: HTTP ${resp.status}`);\n        }\n        let data;\n        try {\n            data = await resp.json();\n        } catch (error) {\n            throw new CommandExecutionError(`archive wayback returned malformed JSON: ${error?.message || error}`);\n        }\n\n        const snap = data?.archived_snapshots?.closest;\n        if (!snap || !snap.available) {\n            throw new EmptyResultError('archive wayback', `No Wayback snapshot for \"${target}\".`);\n        }\n        if (typeof snap.url !== 'string' || !snap.url || !/^\\d{14}$/.test(String(snap.timestamp ?? ''))) {\n            throw new CommandExecutionError('archive wayback returned malformed payload: closest snapshot is missing url/timestamp');\n        }\n\n        return [{\n            original_url: String(data.url ?? target),\n            requested_timestamp: timestamp,\n            snapshot_timestamp: String(snap.timestamp ?? ''),\n            snapshot_url: String(snap.url),\n            status: String(snap.status ?? ''),\n        }];\n    },","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/archive/wayback.js#L46-L82","documentation":"Thrown when the response body from the Wayback Machine save API cannot be parsed as JSON. The library expects the archived_snapshots envelope in the response; an HTML error page, empty body, or truncated response makes resp.json() throw, which is wrapped in a CommandExecutionError. It means the HTTP call succeeded but the body was not valid JSON.","triggerScenarios":"`opencli archive wayback <url>` succeeds at HTTP level but resp.json() throws — e.g. the server returned an HTML interstitial/anti-bot page, a redirect without a body, or a truncated response.","commonSituations":"Wayback serving an HTML captcha or maintenance page with 200 status; proxies/corporate gateways rewriting the response; intermittent network truncation.","solutions":["Retry the command — Wayback sometimes returns transient non-JSON responses","Inspect the raw response by fetching the save URL with curl to see what is actually returned","Check whether a corporate proxy or VPN is injecting HTML into responses","If persistent, check web.archive.org status; the service may be returning error pages with 200 status"],"exampleFix":"// before\nawait exec('opencli archive wayback ' + url);\n// after\ntry {\n  await exec('opencli archive wayback ' + url);\n} catch (e) {\n  if (e.message.includes('malformed JSON')) {\n    console.error('Wayback returned non-JSON (possible HTML error page); retrying...');\n    return await exec('opencli archive wayback ' + url);\n  }\n  throw e;\n}","handlingStrategy":"retry","validationCode":"null","typeGuard":"null","tryCatchPattern":"try {\n  await runWayback(url);\n} catch (e) {\n  if (e.message.includes('malformed JSON')) {\n    await sleep(2000);\n    return runWayback(url); // transient HTML error page — retry once\n  }\n  throw e;\n}","preventionTips":["Retry with backoff — Wayback sometimes returns HTML pages with 200 status","Bypass intercepting proxies/VPNs when archiving","Curl the save endpoint first when debugging to see the raw body","Watch web.archive.org status pages during known incidents"],"tags":["json","parsing","network","archive"],"backgroundTag":"invalid-json-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}