can1357/oh-my-pi · error · ToolError
tab.extract(${JSON.stringify(format)}) produced empty ${form
Error message
tab.extract(${JSON.stringify(format)}) produced empty ${format} content for ${page.url()} What it means
Second-stage validation in `tab.extract`: readability succeeded but the requested format's output (`result.markdown` or `result.text`) is empty/whitespace, so this ToolError is thrown. It covers pages where a readable body exists structurally but contains no textual content in the requested format.
Source
Thrown at packages/coding-agent/src/tools/browser/tab-worker.ts:1652
}
},
),
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);
try {
await untilAborted(sig, () => handle.click());
} finally {
await handle.dispose().catch(() => undefined);
}
return;View on GitHub (pinned to 9690622007)
Solutions
- Try the other format (e.g. 'markdown' instead of 'text') — one projection may retain content the other drops
- Fall back to ariaSnapshot to capture the accessibility tree text instead of readability extraction
- Extract from a specific content element rather than the whole page
- If the content is genuinely non-textual, use a screenshot/visual inspection instead of extract
Example fix
// before
const text = await tab.extract('text'); // empty on gallery page
// after
let content = await tab.extract('text');
if (!content) content = await tab.extract('markdown');
if (!content) content = await tab.ariaSnapshot(); Defensive patterns
Strategy: fallback
Validate before calling
const html = await tab.content();
const textOnly = html.replace(/<[^>]+>/g, '').trim();
if (!textOnly) throw new Error('page has no textual content — extract will be empty'); Try / catch
try {
return await tab.extract(format);
} catch (err) {
if (err instanceof ToolError && err.message.includes('produced empty')) {
for (const f of alternateFormats) {
const c = await tab.extract(f).catch(() => null);
if (c) return c;
}
return await tab.ariaSnapshot();
}
throw err;
} Prevention
- Try multiple extract formats when one projection is empty
- Use ariaSnapshot or screenshots for image/video/canvas-heavy pages
- Extract from a specific content element instead of the whole page when structure is known
- Treat readability as one signal — verify the page actually has text before relying on it
When it happens
Trigger: Requesting a format whose projected content is empty: readability found a container but only images/embeds/no text (e.g. gallery or video page), or the text projection stripped everything.
Common situations: Image/video-dominated pages (Instagram-style galleries); pages where content is canvas/canvas-rendered; extracting 'text' from a page whose body is only links/menus; extraction of a mostly-iframed page.
Related errors
- tab.extract(${JSON.stringify(format)}) found no readable con
- tab.extract(${JSON.stringify(format)}) produced empty ${form
- tab.extract(${JSON.stringify(format)}) found no readable con
- 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/27e6446a9c6ce7af.
Report an issue: GitHub.