{"record":{"id":"27e6446a9c6ce7af","repo":"can1357/oh-my-pi","slug":"tab-extract-json-stringify-format-produced-em-27e644","errorCode":null,"errorMessage":"tab.extract(${JSON.stringify(format)}) produced empty ${format} content for ${page.url()}","messagePattern":"tab\\.extract\\((.+?)\\) produced empty (.+?) content for (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":1652,"sourceCode":"\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t),\n\t\t\tscreenshot: opts =>\n\t\t\t\top(describeScreenshot(opts), quickOpMs, sig =>\n\t\t\t\t\tthis.#captureScreenshot(session, output, screenshots, sig, opts),\n\t\t\t\t),\n\t\t\textract: (format = \"markdown\") =>\n\t\t\t\top(`tab.extract(${JSON.stringify(format)})`, quickOpMs, async sig => {\n\t\t\t\t\tconst html = (await untilAborted(sig, () => page.content())) as string;\n\t\t\t\t\tconst result = await extractReadableFromHtml(html, page.url(), format);\n\t\t\t\t\tif (!result) {\n\t\t\t\t\t\tthrow new ToolError(\n\t\t\t\t\t\t\t`tab.extract(${JSON.stringify(format)}) found no readable content on ${page.url()}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\tconst content = format === \"markdown\" ? result.markdown : result.text;\n\t\t\t\t\tif (!content) {\n\t\t\t\t\t\tthrow new ToolError(\n\t\t\t\t\t\t\t`tab.extract(${JSON.stringify(format)}) produced empty ${format} content for ${page.url()}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn content;\n\t\t\t\t}),\n\t\t\tclick: selector =>\n\t\t\t\top(\n\t\t\t\t\t`tab.click(${JSON.stringify(selector)})`,\n\t\t\t\t\tactionOpMs,\n\t\t\t\t\tasync sig => {\n\t\t\t\t\t\tif (parseAriaRefSelector(selector) !== null) {\n\t\t\t\t\t\t\tconst handle = await this.#resolveAriaRef(selector);\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tawait untilAborted(sig, () => handle.click());\n\t\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\t\tawait handle.dispose().catch(() => undefined);\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\treturn;","sourceCodeStart":1634,"sourceCodeEnd":1670,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L1634-L1670","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst text = await tab.extract('text'); // empty on gallery page\n// after\nlet content = await tab.extract('text');\nif (!content) content = await tab.extract('markdown');\nif (!content) content = await tab.ariaSnapshot();","handlingStrategy":"fallback","validationCode":"const html = await tab.content();\nconst textOnly = html.replace(/<[^>]+>/g, '').trim();\nif (!textOnly) throw new Error('page has no textual content — extract will be empty');","typeGuard":null,"tryCatchPattern":"try {\n  return await tab.extract(format);\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes('produced empty')) {\n    for (const f of alternateFormats) {\n      const c = await tab.extract(f).catch(() => null);\n      if (c) return c;\n    }\n    return await tab.ariaSnapshot();\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["extraction","empty-content","readability","browser-automation"],"backgroundTag":"no-readable-content","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}