{"record":{"id":"9edf8d790ee41946","repo":"jackwener/OpenCLI","slug":"xiaohongshu-search-rendered-in-a-collapsed-tab-bu","errorCode":null,"errorMessage":"Xiaohongshu search rendered in a collapsed tab, but this browser session cannot replace the failed target.","messagePattern":"Xiaohongshu search rendered in a collapsed tab, but this browser session cannot replace the failed target\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/search.js","lineNumber":813,"sourceCode":"        throw new TimeoutError('xiaohongshu search content', CONTENT_WAIT_SECONDS);\n    }\n    if (waitResult !== 'content') {\n        throw new CommandExecutionError('Unexpected Xiaohongshu search wait payload shape.');\n    }\n    requireFilterApplication(await page.evaluate(buildApplySearchFiltersJs(requestedFilters)));\n    const harvestOptions = harvestOptionsForLimit(limit);\n    const harvest = requireHarvestPayload(await page.evaluate(buildScrollHarvestJs('www.xiaohongshu.com', limit, harvestOptions)), 'www.xiaohongshu.com');\n    if (harvest.diag.securityBlock) {\n        throw new CliError('SECURITY_BLOCK', 'Xiaohongshu search was blocked by request-frequency or security controls.', 'Wait before retrying or use a different logged-in browser session.');\n    }\n    return harvest;\n}\n\nasync function replaceCollapsedTab(page, url) {\n    if (typeof page.getActivePage !== 'function' || typeof page.newTab !== 'function' ||\n        typeof page.setActivePage !== 'function' || typeof page.selectTab !== 'function' ||\n        typeof page.closeTab !== 'function') {\n        throw new CommandExecutionError(\n            'Xiaohongshu search rendered in a collapsed tab, but this browser session cannot replace the failed target.',\n            'Retry the command in a Browser Bridge session that supports tab replacement.',\n        );\n    }\n    const previousPage = page.getActivePage();\n    if (!previousPage) {\n        throw new CommandExecutionError('Xiaohongshu search cannot identify the collapsed browser target for safe replacement.');\n    }\n    let freshPage;\n    try {\n        freshPage = await page.newTab(url);\n        if (!freshPage) {\n            throw new Error('newTab returned no page identity');\n        }\n        page.setActivePage(freshPage);\n        await page.closeTab(previousPage);\n    }\n    catch (error) {","sourceCodeStart":795,"sourceCodeEnd":831,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/search.js#L795-L831","documentation":"When the first harvest's diagnostics show a 'collapsed' render (isCollapsedRender), command() calls replaceCollapsedTab to recover by opening the search URL in a fresh tab and closing the broken one. That recovery requires the browser session (Browser Bridge) to expose tab-management APIs: getActivePage, newTab, setActivePage, selectTab, closeTab. If any is missing, this CommandExecutionError is thrown because the session type cannot perform the replacement.","triggerScenarios":"replaceCollapsedTab(page, url) detects typeof page.getActivePage !== 'function' || typeof page.newTab !== 'function' || typeof page.setActivePage !== 'function' || typeof page.selectTab !== 'function' || typeof page.closeTab !== 'function' (clis/xiaohongshu/search.js:810-812) — i.e. a minimal/single-page session object lacking tab APIs while the page rendered collapsed.","commonSituations":"Running the CLI against a plain Playwright/Puppeteer page or a reduced headless session instead of a full Browser Bridge session; an older CLI/browser-bridge version whose session wrapper predates the tab API; embedding the command's func with a stubbed/mock page object in tests.","solutions":["Run the command in a full Browser Bridge session that supports multi-tab management (the remedy named in the error hint).","Upgrade the CLI and its browser-bridge package to matching versions so the session wrapper exposes all five tab methods.","If embedding programmatically, pass a page/session object implementing getActivePage, newTab, setActivePage, selectTab, and closeTab.","Retry later if the collapse is transient — the collapsed render may not recur, avoiding the recovery path entirely."],"exampleFix":"// before: minimal session lacking tab APIs\nconst session = await openSession({ tabs: false });\nawait run('xiaohongshu search', 'coffee');\n// after: full browser-bridge session with tab support\nconst session = await openBridgeSession({ tabManagement: true });\nawait run('xiaohongshu search', 'coffee');","handlingStrategy":"fallback","validationCode":"// Verify the session supports tab replacement before running search\nconst required = ['getActivePage', 'newTab', 'setActivePage', 'selectTab', 'closeTab'];\nconst missing = required.filter((m) => typeof page[m] !== 'function');\nif (missing.length) throw new Error(`Session lacks tab APIs: ${missing.join(', ')}; use a Browser Bridge session`);","typeGuard":"function supportsTabReplacement(page) {\n  return ['getActivePage', 'newTab', 'setActivePage', 'selectTab', 'closeTab']\n    .every((m) => typeof page?.[m] === 'function');\n}","tryCatchPattern":"try {\n  rows = await cli('xiaohongshu search', query);\n} catch (err) {\n  if (err instanceof CommandExecutionError && /cannot replace the failed target/.test(err.message)) {\n    throw new Error('Use a full Browser Bridge session with tab management for xiaohongshu search');\n  }\n  throw err;\n}","preventionTips":["Run the CLI inside a full Browser Bridge session with multi-tab support, not a bare single-page driver.","Check supportsTabReplacement(page) programmatically before invoking search in embedded scripts.","Keep CLI and browser-bridge versions in sync so the session wrapper exposes all tab methods.","In tests, mock pages must implement the five tab APIs if they exercise the collapsed-render path."],"tags":["browser-session","tab-management","capability-check","xiaohongshu"],"backgroundTag":"missing-capability-on-session","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}