jackwener/OpenCLI · error · CommandExecutionError
Reuters search API returned an unreadable response
Error message
Reuters search API returned an unreadable response
What it means
The in-page fetch of the Reuters articles-by-search-v2 API returned a value that is null or not a plain object, so the CLI cannot inspect result.ok/status/body. The library throws this when page.evaluate resolves to something unexpected (undefined, a string, etc.), which usually means the page context was torn down, the evaluation was blocked, or the injected script failed silently before producing its structured result object. It is deliberately distinct from the auth-wall and non-OK cases so the caller knows the response shape itself is wrong.
Source
Thrown at clis/reuters/search.js:36
args: [
{ name: 'query', required: true, positional: true, help: 'Search query' },
{ name: 'limit', type: 'int', default: 10, help: 'Number of results (1-40)' },
],
columns: ['rank', 'title', 'date', 'section', 'section_path', 'authors', 'url'],
func: async (page, kwargs) => {
const limit = parseLimit(kwargs.limit);
const query = String(kwargs.query || '').trim();
if (!query) {
throw new ArgumentError('Search query cannot be empty', 'Provide a non-empty keyword');
}
await page.goto('https://www.reuters.com');
await page.wait(2);
const result = await page.evaluate(buildSearchScript(query, limit));
if (result?.error) {
throw new CommandExecutionError(`Reuters search failed inside the page: ${result.error}`);
}
if (!result || typeof result !== 'object') {
throw new CommandExecutionError('Reuters search API returned an unreadable response');
}
if (isAuthStatus(result.status) || looksAuthWallText(result.textPreview)) {
throw new AuthRequiredError(
'www.reuters.com',
`Reuters search requires an accessible Reuters browser session or completed human verification${result.status ? ` (HTTP ${result.status})` : ''}`,
);
}
if (result.ok !== true) {
const status = Number.isFinite(result.status) && result.status > 0
? `HTTP ${result.status}${result.statusText ? ` ${result.statusText}` : ''}`
: 'no upstream response';
throw new CommandExecutionError(`Reuters search API failed (${status})`);
}
if (!result.body) {
const detail = result.parseError ? `: ${result.parseError}` : '';
throw new CommandExecutionError(
`Reuters search returned a non-JSON body${detail}`,
'Open www.reuters.com in your browser and clear any challenge before retrying.',View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command — transient navigation/teardown of the reuters.com tab often resolves it on a second run.
- Run the auth/login flow so an authenticated, settled www.reuters.com tab exists before searching (Strategy.COOKIE requires it).
- Clear the Datadome challenge by opening www.reuters.com in the browser, then retry.
- Inspect/patch buildSearchScript in clis/reuters/utils.js to guarantee it always returns the structured result object even on internal failure (catch and return {ok:false,error:...}).
Example fix
// before
const result = await page.evaluate(buildSearchScript(query, limit));
// after (guard in the injected script)
const result = await page.evaluate(buildSearchScript(query, limit));
if (!result || typeof result !== 'object') {
await page.goto('https://www.reuters.com');
await page.wait(2);
result = await page.evaluate(buildSearchScript(query, limit));
} Defensive patterns
Strategy: type-guard
Validate before calling
// ensure a settled, authenticated tab before evaluating
await page.goto('https://www.reuters.com');
await page.wait(2);
if (!page.url().includes('reuters.com')) throw new Error('tab redirected away; re-authenticate first'); Type guard
function isSearchResult(v) {
return v !== null && typeof v === 'object' && !Array.isArray(v) && 'ok' in v;
}
const result = await page.evaluate(buildSearchScript(query, limit));
if (!isSearchResult(result)) { /* retry or surface unreadable-response error */ } Try / catch
try {
const rows = await runReutersSearch(query, limit);
} catch (e) {
if (e.message.includes('unreadable response')) {
await page.goto('https://www.reuters.com'); await page.wait(2);
rows = await runReutersSearch(query, limit); // one retry
} else throw e;
} Prevention
- Always land on and settle www.reuters.com before evaluating in-page scripts.
- Make the injected script return {ok:false,error:...} on internal failure instead of nothing.
- Wrap page.evaluate in a retry for transient tab teardown.
- Log page.url() and a text snapshot when the result shape is wrong to diagnose redirection.
When it happens
Trigger: page.evaluate(buildSearchScript(query, limit)) resolves to null/undefined/non-object — e.g. the injected IIFE threw before returning, the tab navigated away mid-evaluate, or the browser returned a serialized primitive.
Common situations: Reuters page redirected or reloaded while the search script ran; Datadome replaced the document so the script never returned its object; browser session timed out; a bug/version change in buildSearchScript stops it from returning a value.
Related errors
- Barchart greeks request failed: ${data.message || 'unknown e
- Failed to load Booking.com search page: ${err?.message || er
- Failed to open Chess.com analysis board: ${error?.message ||
- Failed to send message
- coupang search filtered navigation failed: ${error?.message
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/4d3adff6bfcd334b.
Report an issue: GitHub.