{"record":{"id":"0af58bd053dde3e0","repo":"can1357/oh-my-pi","slug":"tab-extract-json-stringify-format-found-no-re-0af58b","errorCode":null,"errorMessage":"tab.extract(${JSON.stringify(format)}) found no readable content on ${page.url()}","messagePattern":"tab\\.extract\\((.+?)\\) found no readable content on (.+?)","errorType":"exception","errorClass":"ToolError","httpStatus":null,"severity":"error","filePath":"packages/coding-agent/src/tools/browser/tab-worker.ts","lineNumber":1646,"sourceCode":"\t\t\t\t\t\t\t\t);\n\t\t\t\t\t\t}\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\treturn await untilAborted(sig, () => captureAriaSnapshot(page, root, opts));\n\t\t\t\t\t\t} finally {\n\t\t\t\t\t\t\tawait root?.dispose().catch(() => undefined);\n\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);","sourceCodeStart":1628,"sourceCodeEnd":1664,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/coding-agent/src/tools/browser/tab-worker.ts#L1628-L1664","documentation":"`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).","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nconst md = await tab.extract('markdown'); // SPA shell, empty body\n// after\nawait tab.wait(() => locationReady && document.querySelector('main article'), { timeout: 10000 });\nconst md = await tab.extract('markdown');","handlingStrategy":"fallback","validationCode":"const html = await tab.content();\nif (html.trim().length < 500) throw new Error('page appears empty/unrendered — skip extract');","typeGuard":null,"tryCatchPattern":"try {\n  return await tab.extract('markdown');\n} catch (err) {\n  if (err instanceof ToolError && err.message.includes('found no readable content')) {\n    return await tab.ariaSnapshot(); // accessibility tree as fallback content\n  }\n  throw err;\n}","preventionTips":["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"],"tags":["extraction","readability","content","browser-automation"],"backgroundTag":"no-readable-content","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}