{"record":{"id":"585004207c484051","repo":"jackwener/OpenCLI","slug":"unexpected-xiaohongshu-search-filter-result-shape","errorCode":null,"errorMessage":"Unexpected Xiaohongshu search filter result shape.","messagePattern":"Unexpected Xiaohongshu search filter result shape\\.","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaohongshu/search.js","lineNumber":500,"sourceCode":"          }\n          if (stableSamples < 3) {\n            return { status: 'timeout', detail: request.group + '/' + request.option };\n          }\n          const finalPanels = panels();\n          const finalFound = finalPanels.length === 1 ? findOption(finalPanels[0], request) : null;\n          if (!finalFound || finalFound.status !== 'ok' || !isActive(finalFound.option)) {\n            return { status: 'inactive', detail: request.group + '/' + request.option };\n          }\n        }\n        return { status: 'ok' };\n      })()\n    `;\n}\n\nfunction requireFilterApplication(payload) {\n    const result = unwrapEvaluateResult(payload);\n    if (!result || typeof result !== 'object' || Array.isArray(result) || typeof result.status !== 'string') {\n        throw new CommandExecutionError('Unexpected Xiaohongshu search filter result shape.');\n    }\n    if (result.status === 'ok') {\n        return;\n    }\n    const detail = typeof result.detail === 'string' ? result.detail : 'unknown';\n    if (result.status === 'auth') {\n        throw new AuthRequiredError('www.xiaohongshu.com', 'Xiaohongshu search filters require a logged-in browser session');\n    }\n    if (result.status === 'timeout') {\n        throw new TimeoutError(`xiaohongshu search filter ${detail}`, FILTER_SETTLE_SECONDS);\n    }\n    if (result.status === 'location') {\n        throw new CommandExecutionError(`Xiaohongshu location filter was not applied (${detail}); enable browser geolocation permission.`);\n    }\n    if (result.status === 'capability') {\n        throw new CommandExecutionError(`Xiaohongshu account-scoped filter was unavailable (${detail}); verify login and account access.`);\n    }\n    if (result.status === 'inactive') {","sourceCodeStart":482,"sourceCodeEnd":518,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaohongshu/search.js#L482-L518","documentation":"requireFilterApplication validates the result of the in-browser script that applies search filter chips. The payload must unwrap to a non-array object with a string status field; otherwise this CommandExecutionError is thrown. It means the filter-application script did not return the expected {status, detail} contract at all.","triggerScenarios":"page.evaluate for filter application returns undefined/null (script crashed, page navigated mid-run), returns an array, or the browser driver wraps the result in an unexpected structure that unwrapEvaluateResult cannot normalize.","commonSituations":"Xiaohongshu redirected the page (login wall, anti-bot) while the filter script ran; a DOM change threw inside the injected script so it never returned a status; driver/CDP serialization quirks dropping the return value.","solutions":["Log the raw evaluate payload before validation to see what actually came back","Ensure the search results page is loaded and stable (no redirect/login wall) before applying filters","Update the injected filter script to catch its own errors and return {status:'error', detail} instead of throwing","Verify unwrapEvaluateResult handles your specific browser driver's result wrapping"],"exampleFix":"// before\nconst result = unwrapEvaluateResult(payload);\nif (!result || typeof result !== 'object' || Array.isArray(result) || typeof result.status !== 'string') {\n  throw new CommandExecutionError('Unexpected Xiaohongshu search filter result shape.');\n}\n// after\nconst result = unwrapEvaluateResult(payload);\nif (!result || typeof result !== 'object' || Array.isArray(result) || typeof result.status !== 'string') {\n  console.error('filter payload:', JSON.stringify(payload));\n  throw new CommandExecutionError('Unexpected Xiaohongshu search filter result shape; check for login walls or DOM changes.');\n}","handlingStrategy":"type-guard","validationCode":"function looksLikeFilterResult(p) {\n  const r = p?.value ?? p;\n  return !!r && typeof r === 'object' && !Array.isArray(r) && typeof r.status === 'string';\n}\nif (!looksLikeFilterResult(rawFilterPayload)) throw new Error('filter script returned unexpected shape');","typeGuard":"const isFilterResult = (r) =>\n  r !== null && typeof r === 'object' && !Array.isArray(r) && typeof r.status === 'string';","tryCatchPattern":"try {\n  requireFilterApplication(raw);\n} catch (e) {\n  if (e.message.includes('filter result shape')) {\n    console.error('raw filter payload:', JSON.stringify(raw));\n    // page likely navigated or the injected script crashed; reload and retry once\n  } else throw e;\n}","preventionTips":["Wrap the injected filter script body in try/catch so it always returns a {status, detail} object","Wait for the search results page to be stable before applying filters","Test the filter flow against the live Xiaohongshu DOM after UI redesigns","Confirm your browser driver's evaluate result wrapping is handled by unwrapEvaluateResult"],"tags":["schema-validation","scraping","payload-shape","filters"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}