can1357/oh-my-pi · error · ToolError
tab.extract(${JSON.stringify(format)}) found no readable con
Error message
tab.extract(${JSON.stringify(format)}) found no readable content on ${page.url()} What it means
`tab.extract(format)` fetches page HTML and runs extractReadableFromHtml; when the readability extraction returns null — no article/readable body could be identified — this ToolError is thrown. It signals the page has no extractable main content (not that extraction merely failed to parse).
Source
Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:1646
);
}
try {
return await untilAborted(sig, () => captureAriaSnapshot(page, root, opts));
} finally {
await root?.dispose().catch(() => undefined);
}
},
),
screenshot: opts =>
op(describeScreenshot(opts), quickOpMs, sig =>
this.#captureScreenshot(session, output, screenshots, sig, opts),
),
extract: (format = "markdown") =>
op(`tab.extract(${JSON.stringify(format)})`, quickOpMs, async sig => {
const html = (await untilAborted(sig, () => page.content())) as string;
const result = await extractReadableFromHtml(html, page.url(), format);
if (!result) {
throw new ToolError(
`tab.extract(${JSON.stringify(format)}) found no readable content on ${page.url()}`,
);
}
const content = format === "markdown" ? result.markdown : result.text;
if (!content) {
throw new ToolError(
`tab.extract(${JSON.stringify(format)}) produced empty ${format} content for ${page.url()}`,
);
}
return content;
}),
click: selector =>
op(
`tab.click(${JSON.stringify(selector)})`,
actionOpMs,
async sig => {
if (parseAriaRefSelector(selector) !== null) {
const handle = await this.#resolveAriaRef(selector);View on GitHub (pinned to 9690622007)
Solutions
- Wait for the app to render (wait for a content selector) before extracting
- Fall back to ariaSnapshot or tab content/screenshot to inspect what the page actually contains
- Check the URL — verify it is not an error/interstitial page and that authentication state is established
- Use a different format or extract from a specific element if the page has content readability misclassifies
Example fix
// before
const md = await tab.extract('markdown'); // SPA shell, empty body
// after
await tab.wait(() => locationReady && document.querySelector('main article'), { timeout: 10000 });
const md = await tab.extract('markdown'); Defensive patterns
Strategy: fallback
Validate before calling
const html = await tab.content();
if (html.trim().length < 500) throw new Error('page appears empty/unrendered — skip extract'); Try / catch
try {
return await tab.extract('markdown');
} catch (err) {
if (err instanceof ToolError && err.message.includes('found no readable content')) {
return await tab.ariaSnapshot(); // accessibility tree as fallback content
}
throw err;
} Prevention
- Wait for app hydration/render before extracting from SPAs
- Authenticate before extracting from gated pages
- Detect error/interstitial pages (status codes, consent walls) before extracting
- Prefer article-like URLs when the goal is readable content
When it happens
Trigger: Extracting from pages readability cannot model: login-gated shells, pure JS-app skeletons with empty SSR HTML, error pages, cookie/consent walls, PDF/image-only pages, or pages whose main content lives in iframes.
Common situations: Extracting from a SPA before hydration completed; scraping a search results page or dashboard with no article semantics; hitting a paywall/interstitial; extracting from a 404/500 response body.
Related errors
- tab.extract(${JSON.stringify(format)}) produced empty ${form
- tab.extract(${JSON.stringify(format)}) found no readable con
- tab.extract(${JSON.stringify(format)}) produced empty ${form
- tab.select() requires a <select> element
- Unsupported selector action ${action}
AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31).
Data as JSON: /api/errors/0af58bd053dde3e0.
Report an issue: GitHub.