jackwener/OpenCLI · error · CommandExecutionError

archive search returned malformed payload: response.docs mus

Error message

archive search returned malformed payload: response.docs must be an array

What it means

This CommandExecutionError is thrown when the archive.org advancedsearch response parses as JSON but `data.response.docs` is missing or not an array. The CLI expects the standard Lucene/advancedsearch envelope ({ response: { docs: [...] } }) and refuses to proceed on any other shape. It indicates an unexpected API payload rather than caller input error.

Source

Thrown at clis/archive/search.js:87

                    'User-Agent': 'opencli/1.0 (+https://github.com/jackwener/opencli)',
                },
            });
        } catch (error) {
            throw new CommandExecutionError(`archive search request failed: ${error?.message || error}`);
        }
        if (!resp.ok) {
            throw new CommandExecutionError(`archive search failed: HTTP ${resp.status}`);
        }
        let data;
        try {
            data = await resp.json();
        } catch (error) {
            throw new CommandExecutionError(`archive search returned malformed JSON: ${error?.message || error}`);
        }

        const docs = data?.response?.docs;
        if (!Array.isArray(docs)) {
            throw new CommandExecutionError('archive search returned malformed payload: response.docs must be an array');
        }
        if (docs.length === 0) {
            throw new EmptyResultError('archive search', `No items match "${query}" on archive.org.`);
        }

        return docs.slice(0, limit).map((d, i) => {
            const id = String(d.identifier ?? '');
            if (!IDENTIFIER_RE.test(id)) {
                throw new CommandExecutionError('archive search returned malformed payload: result row is missing a stable identifier');
            }
            const downloads = Number(d.downloads ?? 0);
            if (!Number.isFinite(downloads)) {
                throw new CommandExecutionError(`archive search returned malformed payload for "${id}": downloads must be numeric`);
            }
            const creator = Array.isArray(d.creator) ? d.creator.join(', ') : String(d.creator ?? '');
            return {
                rank: i + 1,
                identifier: id,

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the raw JSON (`curl ... | jq`) to see what shape was actually returned
  2. Check the query syntax — backend-rejected queries may come back as JSON without a response.docs envelope
  3. Retry later in case of archive.org schema changes or incidents; check status.archive.org
  4. Catch this error and surface the raw payload for diagnostics instead of letting it fail silently in pipelines

Example fix

// before
const { docs } = await searchArchive(query);
// after
const result = await searchArchive(query);
if (!Array.isArray(result?.response?.docs)) {
    console.error('unexpected payload:', JSON.stringify(result).slice(0, 500));
    process.exit(1);
}
const { docs } = result.response;
Defensive patterns

Strategy: type-guard

Validate before calling

const raw = await fetch(url).then(r => r.json());
if (!Array.isArray(raw?.response?.docs)) {
    console.error('unexpected envelope:', JSON.stringify(raw).slice(0, 500));
}

Type guard

function hasDocsEnvelope(data) {
    return Boolean(data) && typeof data === 'object' && Array.isArray(data?.response?.docs);
}

Try / catch

try {
    rows = await run(['archive', 'search', query]);
} catch (err) {
    if (err instanceof CommandExecutionError && err.message.includes('response.docs must be an array')) {
        console.error('archive.org returned a non-standard envelope; check query syntax or API status');
    } else { throw err; }
}

Prevention

When it happens

Trigger: Calling `opencli archive search ...` when archive.org returns a JSON error object (e.g. { error: ... }) instead of the response envelope, an API schema change, or an intermediary returning valid JSON of the wrong shape (e.g. a JSON error page from a proxy).

Common situations: Malformed query syntax that the backend rejects but returns as JSON 200; archive.org API drift or beta endpoints; corporate proxies substituting their own JSON error payloads; script errors hitting a mirror/clone with a different response shape.

Understand the failure class

Related errors


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