{"record":{"id":"94fe632ec71fe2a9","repo":"jackwener/OpenCLI","slug":"xiaohongshu-collection-page-returned-malformed-loc","errorCode":null,"errorMessage":"xiaohongshu collection page returned malformed location","messagePattern":"xiaohongshu collection page returned malformed location","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/collection-helpers.js","lineNumber":190,"sourceCode":"  (() => ({\n    href: location.href,\n    hostname: location.hostname,\n    pathname: location.pathname,\n  }))()\n`;\n\nasync function throwIfLoginWall(page) {\n    const payload = unwrapBrowserResult(await page.evaluate(LOGIN_WALL_JS));\n    if (payload === true) {\n        throw new AuthRequiredError('www.xiaohongshu.com', 'Xiaohongshu collection page requires login; re-login to xiaohongshu.com and retry.');\n    }\n}\n\nexport async function assertOnCollectionProfile(page, userId) {\n    await throwIfLoginWall(page);\n    const payload = unwrapBrowserResult(await page.evaluate(CURRENT_LOCATION_JS));\n    if (!isObject(payload)) {\n        throw new CommandExecutionError('xiaohongshu collection page returned malformed location');\n    }\n    const hostname = toCleanString(payload.hostname).toLowerCase();\n    const pathname = toCleanString(payload.pathname);\n    if (hostname === 'www.xiaohongshu.com' && pathname === '/login') {\n        throw new AuthRequiredError('xiaohongshu collection page requires login');\n    }\n    const expectedPath = `/user/profile/${toCleanString(userId)}`;\n    if (hostname !== 'www.xiaohongshu.com' || pathname !== expectedPath) {\n        throw new CommandExecutionError(`xiaohongshu collection landed on unexpected page: ${toCleanString(payload.href) || `${hostname}${pathname}`}`);\n    }\n}\n\nasync function accumulateInterceptedNotes(page, bucket, fallbackUserId) {\n    const reqs = await page.getInterceptedRequests();\n    if (!Array.isArray(reqs)) {\n        throw new CommandExecutionError('xiaohongshu collection interceptor returned malformed captures');\n    }\n    if (Array.isArray(reqs) && reqs.length > 0)","sourceCodeStart":172,"sourceCodeEnd":208,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/collection-helpers.js#L172-L208","documentation":"assertOnCollectionProfile evaluates CURRENT_LOCATION_JS and requires the page to report its location as an object (hostname/pathname/href). A non-object result means the location probe failed or returned something unexpected, so CommandExecutionError is thrown. This validates navigation landed on a real page before path checks.","triggerScenarios":"page.evaluate(CURRENT_LOCATION_JS) returns undefined/null (script failed, page navigated mid-eval, destroyed context) or unwrapBrowserResult yields a non-object (e.g. string error).","commonSituations":"Browser tab navigated or closed during scraping; CDP evaluation failed silently; heavy page redirects racing with the check; automation browser version mismatch breaking evaluate return values.","solutions":["Ensure the page is fully loaded before calling fetchXhsCollectionNotes (wait for network idle)","Check the browser/tab wasn't closed or navigated away mid-run","Update the automation browser driver — stale evaluate contexts return undefined","Add a retry that reloads the collection profile URL then re-asserts"],"exampleFix":"// before\nconst notes = await fetchXhsCollectionNotes(page, userId); // malformed location\n// after\nawait page.goto(collectionUrl, { waitUntil: 'networkidle' });\nif (page.isClosed()) throw new Error('page closed before scraping');\nconst notes = await fetchXhsCollectionNotes(page, userId);","handlingStrategy":"try-catch","validationCode":"if (page.isClosed?.()) throw new Error('page closed before location check');\nconst loc = await page.evaluate(() => ({ href: location.href }));\nif (!loc || typeof loc !== 'object') await page.reload();","typeGuard":"const isLocation = (v) => v !== null && typeof v === 'object' && typeof v.href === 'string';","tryCatchPattern":"try { notes = await fetchXhsCollectionNotes(page, userId); } catch (e) { if (String(e.message).includes('malformed location')) { await page.goto(collectionUrl, { waitUntil: 'networkidle' }); notes = await fetchXhsCollectionNotes(page, userId); } else throw e; }","preventionTips":["Wait for networkidle/load before asserting page state","Check page.isClosed() before evaluate calls","Avoid navigating the page concurrently with scraping","Pin compatible versions of the browser-automation wrapper"],"tags":["scraping","page-navigation","command-execution-error"],"backgroundTag":"malformed-api-response","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}