{"record":{"id":"933ca31815746d9f","repo":"jackwener/OpenCLI","slug":"archive-search-returned-malformed-payload-result","errorCode":null,"errorMessage":"archive search returned malformed payload: result row is missing a stable identifier","messagePattern":"archive search returned malformed payload: result row is missing a stable identifier","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/archive/search.js","lineNumber":96,"sourceCode":"        let data;\n        try {\n            data = await resp.json();\n        } catch (error) {\n            throw new CommandExecutionError(`archive search returned malformed JSON: ${error?.message || error}`);\n        }\n\n        const docs = data?.response?.docs;\n        if (!Array.isArray(docs)) {\n            throw new CommandExecutionError('archive search returned malformed payload: response.docs must be an array');\n        }\n        if (docs.length === 0) {\n            throw new EmptyResultError('archive search', `No items match \"${query}\" on archive.org.`);\n        }\n\n        return docs.slice(0, limit).map((d, i) => {\n            const id = String(d.identifier ?? '');\n            if (!IDENTIFIER_RE.test(id)) {\n                throw new CommandExecutionError('archive search returned malformed payload: result row is missing a stable identifier');\n            }\n            const downloads = Number(d.downloads ?? 0);\n            if (!Number.isFinite(downloads)) {\n                throw new CommandExecutionError(`archive search returned malformed payload for \"${id}\": downloads must be numeric`);\n            }\n            const creator = Array.isArray(d.creator) ? d.creator.join(', ') : String(d.creator ?? '');\n            return {\n                rank: i + 1,\n                identifier: id,\n                title: String(d.title ?? ''),\n                creator,\n                date: d.date ? String(d.date).slice(0, 10) : '',\n                mediatype: String(d.mediatype ?? ''),\n                downloads,\n                url: id ? `https://archive.org/details/${id}` : '',\n            };\n        });\n    },","sourceCodeStart":78,"sourceCodeEnd":114,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/archive/search.js#L78-L114","documentation":"CommandExecutionError thrown during result mapping in `opencli archive search` when a row in response.docs has an identifier that is missing or fails IDENTIFIER_RE, the library's pattern for a stable archive.org identifier. The library treats every row as required to carry a usable identifier because downstream commands key off it; a row without one means the payload shape is not what was expected.","triggerScenarios":"The archive.org search API returns docs whose rows lack an `identifier` field (or contain one that is empty/does not match the identifier regex), typically when the query syntax triggers a non-standard response shape.","commonSituations":"archive.org returning odd rows for malformed or edge-case queries; API schema drift where field names change; querying with syntax that returns metadata-only documents instead of items; intermediaries/proxies altering the response.","solutions":["Inspect the raw API response with the same query against https://archive.org/advancedsearch.php to see which row lacks a valid identifier.","Simplify or correct the query — malformed queries can return rows with missing identifier fields.","Report/retry later if archive.org is returning degraded payloads (transient server-side issue).","If you control the query programmatically, validate the response.docs shape yourself before mapping and skip rows without identifiers."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Validate rows before mapping, mirroring IDENTIFIER_RE expectations\nconst IDENTIFIER_RE = /^[\\w.:-]+$/; // adjust to the library's pattern\nconst bad = docs.filter(d => !IDENTIFIER_RE.test(String(d.identifier ?? '')));\nif (bad.length) console.warn(`skipping ${bad.length} rows without a stable identifier`);","typeGuard":"function hasStableIdentifier(row) {\n  return typeof row?.identifier === 'string' && row.identifier.length > 0;\n}","tryCatchPattern":"try {\n  const rows = await run(['archive', 'search', query]);\n} catch (e) {\n  if (/missing a stable identifier/.test(e.message)) {\n    // retry with a simplified query or surface a data-quality warning\n    return retryWithSimplifiedQuery(query);\n  }\n  throw e;\n}","preventionTips":["Avoid exotic query syntax that produces non-item rows.","Spot-check the raw advancedsearch.php JSON for new queries.","Pin/report library versions when archive.org schema changes."],"tags":["malformed-payload","api-schema","archive-org","data-validation"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}