jackwener/OpenCLI · error · CommandExecutionError
Failed to read xiaoe catalog: ${message}
Error message
Failed to read xiaoe catalog: ${message} What it means
getXiaoeCatalog wraps page.goto(url) plus the injected catalog extraction script in try/catch; any navigation or evaluation failure is rethrown as CommandExecutionError('Failed to read xiaoe catalog: <original message>') with the hint that the page may not have rendered or auth may be required.
Source
Thrown at clis/xiaoe/catalog.js:196
resource_id: resId,
url: urlPath ? origin + urlPath + resId + '?type=2' : '',
status: child.is_finish === 1 ? '已完成' : (child.learn_progress > 0 ? child.learn_progress + '%' : '未学'),
});
}
}
return result;
})()`;
}
async function getXiaoeCatalog(page, args) {
const url = requireXiaoePageUrl(args.url, 'catalog');
let rows;
try {
await page.goto(url, { waitUntil: 'load', settleMs: 8000 });
rows = await page.evaluate(buildCatalogScript());
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
throw new CommandExecutionError(
`Failed to read xiaoe catalog: ${message}`,
'page may not have rendered or auth may be required',
);
}
if (!Array.isArray(rows) || rows.length === 0) {
throw new EmptyResultError(
'xiaoe/catalog',
'No catalog rows extracted — the URL may not be a course page or the login session has expired',
);
}
return rows;
}
export const catalogCommand = cli({
site: 'xiaoe',
name: 'catalog',
access: 'read',
description: '小鹅通课程目录(支持普通课程、专栏、大专栏)',View on GitHub (pinned to 49907e53dc)
Solutions
- Read the inner message to identify the root cause (navigation vs evaluate failure).
- Re-authenticate via the xiaoe login flow if the session expired, then retry.
- Retry on transient network errors / increase settleMs for slow pages.
- If the inner error is a script TypeError, update buildCatalogScript() for changed catalog markup.
Example fix
// before
rows = await page.evaluate(buildCatalogScript());
// after
try {
rows = await page.evaluate(buildCatalogScript());
} catch (e) {
await runXiaoeLogin(page); // refresh session before giving up
rows = await page.evaluate(buildCatalogScript());
} Defensive patterns
Strategy: try-catch
Validate before calling
await assertXiaoeAuthed(page); // ensure session before navigation new URL(url); // throws early on a malformed URL
Type guard
function isHttpsUrl(u) { try { return new URL(u).protocol === 'https:'; } catch { return false; } } Try / catch
try {
rows = await getXiaoeCatalog(page, url);
} catch (e) {
if (e instanceof CommandExecutionError && /Failed to read xiaoe catalog/.test(e.message)) {
await runXiaoeLogin(page);
rows = await getXiaoeCatalog(page, url); // one retry after re-auth
} else throw e;
} Prevention
- Verify the session before navigating to catalog pages.
- Retry once on transient navigation/evaluation errors.
- Check the inner message to distinguish network vs script failures.
When it happens
Trigger: page.goto(url,{waitUntil:'load',settleMs:8000}) throws (net error, timeout, navigation aborted) or page.evaluate(buildCatalogScript()) throws inside the page context, for a catalog URL.
Common situations: Expired login causing server-side redirect/error page whose DOM the script cannot parse; network/DNS failure or corporate proxy blocking the domain; catalog page changed markup so the injected script throws (e.g. null selector access); 8s settle too short for a slow SPA.
Related errors
- 1point3acres request failed: ${error?.message || error}
- 1point3acres request failed: HTTP ${res.status} ${res.status
- Barchart greeks request failed: HTTP ${data.status}${data.st
- dianping could not resolve cityId for '${cityArg}' (pinyin=$
- Douyin search extraction failed: ${error instanceof Error ?
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/801170c330a0ceba.
Report an issue: GitHub.