jackwener/OpenCLI · error · CommandExecutionError
WeRead in-book search returned malformed result
Error message
WeRead in-book search returned malformed result
What it means
searchWithinBook calls the WeRead in-book search endpoint via fetchJson and requires data.result to be an array. When the response is missing, null, or has a non-array result field, it throws this CommandExecutionError because pagination cannot proceed on a malformed payload.
Source
Thrown at clis/weread/book-search.js:289
return searchBookByQuery(target, bookRank);
}
async function searchWithinBook(bookId, query, limit, fragmentSize) {
const rows = [];
let maxIdx = 0;
while (rows.length < limit) {
const remaining = limit - rows.length;
const pageSize = remaining < SEARCH_PAGE_SIZE ? remaining : SEARCH_PAGE_SIZE;
const url = new URL('/web/book/search', WEREAD_WEB_ORIGIN);
url.searchParams.set('bookId', bookId);
url.searchParams.set('keyword', query);
url.searchParams.set('maxIdx', String(maxIdx));
url.searchParams.set('count', String(pageSize));
url.searchParams.set('fragmentSize', String(fragmentSize));
url.searchParams.set('onlyCount', '0');
const data = await fetchJson(url, 'WeRead in-book search');
if (!Array.isArray(data?.result)) {
throw new CommandExecutionError('WeRead in-book search returned malformed result');
}
const result = data.result.map((item) => {
if (!item || typeof item !== 'object') {
throw new CommandExecutionError('WeRead in-book search returned malformed match');
}
const snippet = normalizeSearchText(item.abstract);
const searchIdx = parseOptionalFiniteNumber(item.searchIdx);
if (!snippet || searchIdx == null || searchIdx <= 0) {
throw new CommandExecutionError('WeRead in-book search returned malformed match');
}
return {
...item,
abstract: snippet,
chapterIdx: parseOptionalFiniteNumber(item.chapterIdx),
chapterUid: parseOptionalFiniteNumber(item.chapterUid),
searchIdx,
};
});View on GitHub (pinned to 49907e53dc)
Solutions
- Log the raw response body to see the actual envelope and adjust expectations.
- Re-authenticate / refresh cookies if the endpoint returned an error envelope.
- Check for a WeRead API schema update and update the parser.
- Retry later if the endpoint is throttling.
Defensive patterns
Strategy: retry
Type guard
function hasResultArray(data) {
return data != null && typeof data === 'object' && Array.isArray(data.result);
} Try / catch
try {
return await searchWithinBook(bookId, query);
} catch (e) {
if (e instanceof CommandExecutionError && e.message.includes('malformed result')) {
await sleep(1500);
return searchWithinBook(bookId, query); // transient error envelope
}
throw e;
} Prevention
- Refresh auth/cookies when the API starts returning error envelopes.
- Rate-limit calls to avoid degraded responses.
- Log raw responses in a debug mode to catch schema changes early.
When it happens
Trigger: The in-book search API responds with JSON whose shape differs from expected — e.g. {code: -1} error envelope, an object instead of array, or result omitted — after a successful HTTP 200.
Common situations: WeRead API version change; rate limiting or auth expiry returning an error envelope with HTTP 200; searching in a book whose index isn't searchable.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- WeRead book search result ${bookRank} is missing bookId
- WeRead in-book search returned malformed match
- book-rank must be <= ${books.length}
- WeRead in-book search returned malformed pagination state
- weread book-search: No matches for "${query}" in book ${book
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8f4b846632dba52a.
Report an issue: GitHub.