jackwener/OpenCLI · error
HTTP ${resp.status} ${resp.statusText} from ${urls[i]}
Error message
HTTP ${resp.status} ${resp.statusText} from ${urls[i]} What it means
fetchBatchInBrowser runs inside browser evaluate() context and fetches a list of URLs concurrently with a worker pool. When a response is not ok it throws a plain Error whose message embeds the status, statusText, and URL; the catch block stores that message in results[i] as { error: message } rather than rejecting. It is not a typed CliError because CliError/getErrorMessage are Node.js utilities unavailable inside evaluate().
Source
Thrown at src/pipeline/steps/fetch.ts:70
const urlsJs = JSON.stringify(urls);
const methodJs = JSON.stringify(method);
return (await page.evaluate(`
async () => {
const urls = ${urlsJs};
const method = ${methodJs};
const headers = ${headersJs};
const concurrency = ${concurrency};
const results = new Array(urls.length);
let idx = 0;
async function worker() {
while (idx < urls.length) {
const i = idx++;
try {
const resp = await fetch(urls[i], { method, headers, credentials: "include" });
if (!resp.ok) {
throw new Error('HTTP ' + resp.status + ' ' + resp.statusText + ' from ' + urls[i]);
}
results[i] = await resp.json();
} catch (e) {
results[i] = { error: e instanceof Error ? e.message : String(e) };
// Note: getErrorMessage() is a Node.js utility — can't use it inside evaluate()
}
}
}
const workers = Array.from({ length: Math.min(concurrency, urls.length) }, () => worker());
await Promise.all(workers);
return results;
}
`)) as unknown[];
}
export async function stepFetch(page: IPage | null, params: unknown, data: unknown, args: Record<string, unknown>): Promise<unknown> {
const paramObject = isRecord(params) ? params : {};View on GitHub (pinned to 49907e53dc)
Solutions
- Scan results for entries with an .error property and read the embedded status/URL to identify the failing endpoint
- Fix or remove the failing URL from the batch list
- Re-authenticate so the include-credentials cookie session is valid for 401/403
- Reduce worker concurrency or add retry/backoff for 429/5xx responses
Example fix
// before
const results = await fetchBatchInBrowser(urls, { method: 'GET', headers });
console.log(results[3].data); // undefined, results[3] = { error: 'HTTP 404 Not Found from ...' }
// after
const results = await fetchBatchInBrowser(urls, { method: 'GET', headers });
for (const r of results) if (r.error) console.warn('failed:', r.error); Defensive patterns
Strategy: validation
Validate before calling
const bad = urls.filter(u => { try { new URL(u); return false; } catch { return true; } });
if (bad.length) throw new Error('invalid batch urls: ' + bad.join(', ')); Type guard
function hasBatchErrors(results: unknown[]): results is Array<{ error: string }> {
return results.some(r => typeof r === 'object' && r !== null && 'error' in r);
} Try / catch
// Errors are captured per-item in results, not thrown:
const results = await fetchBatchInBrowser(urls, { method, headers });
for (const [i, r] of results.entries()) {
if (r && typeof r === 'object' && 'error' in r) {
console.warn(`batch item ${i} failed: ${r.error}`);
}
} Prevention
- Pre-flight check each URL in the batch resolves and the session cookie is fresh
- Cap worker concurrency and add backoff to avoid 429s from burst traffic
- Always inspect results for { error } entries instead of assuming all succeeded
- Keep browser-side code free of Node-only utilities (as the source comment notes)
When it happens
Trigger: Any URL in the batch array returning a non-ok response (404, 401, 403, 429, 5xx) during fetch(urls[i], { method, headers, credentials: 'include' }). The failure is recorded per-index instead of aborting the whole batch.
Common situations: One dead or renamed endpoint among many batched URLs, cookies expired so credentials:'include' requests get 401, server rate-limiting the burst of parallel requests (429), CORS or auth failures specific to the browser context.
Related errors
- 12306 queryByTrainNo returned HTTP ${resp.status}
- 12306 queryByTrainNo returned non-JSON body
- 12306 ${endpoint} returned non-JSON body
- 1point3acres request failed: HTTP ${res.status} ${res.status
- ${label} returned HTTP ${resp.status}: ${summarizeApiError(p
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/6c44a42d799cae00.
Report an issue: GitHub.