{"record":{"id":"808175f981c1ecff","repo":"jackwener/OpenCLI","slug":"xianyu-search-requires-a-logged-in-browser-session","errorCode":null,"errorMessage":"Xianyu search requires a logged-in browser session","messagePattern":"Xianyu search requires a logged-in browser session","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/xianyu/search.js","lineNumber":225,"sourceCode":"    columns: ['item_id', 'rank', 'title', 'price', 'condition', 'brand', 'location', 'badge', 'want', 'url'],\n    func: async (page, kwargs) => {\n        const query = String(kwargs.query || '').trim();\n        const limit = normalizeLimit(kwargs.limit);\n        const minPrice = parsePriceArg(kwargs['min-price'], 'min-price');\n        const maxPrice = parsePriceArg(kwargs['max-price'], 'max-price');\n        if (minPrice != null && maxPrice != null && minPrice > maxPrice) {\n            throw new ArgumentError('xianyu search min-price cannot be greater than max-price', `Received --min-price ${minPrice} and --max-price ${maxPrice}`);\n        }\n        const province = String(kwargs.province || '').trim();\n        const city = String(kwargs.city || '').trim();\n        const searchFilter = buildSearchFilter(minPrice, maxPrice);\n        const extraFilterValue = buildExtraFilterValue(province, city);\n        const fromFilter = Boolean(searchFilter) || extraFilterValue !== '{}';\n        await page.goto(buildSearchUrl(query));\n        await page.wait(2);\n        const result = await page.evaluate(buildSearchEvaluate({ keyword: query, searchFilter, extraFilterValue, fromFilter, maxItems: limit }));\n        if (result?.error === 'auth-required') {\n            throw new AuthRequiredError('www.goofish.com', 'Xianyu search requires a logged-in browser session');\n        }\n        if (result?.error === 'blocked') {\n            throw new CommandExecutionError('Xianyu returned a verification page or blocked the current browser session');\n        }\n        if (result?.error === 'mtop-not-ready') {\n            throw selectorError('window.lib.mtop', '闲鱼页面未完成初始化，无法调用搜索接口');\n        }\n        if (!result || typeof result !== 'object') {\n            throw new CommandExecutionError('Xianyu search returned a malformed response');\n        }\n        const errorCode = String(result?.error_code || '');\n        const errorMessage = String(result?.error_message || '');\n        if (/FAIL_SYS_SESSION_EXPIRED|SESSION_EXPIRED|FAIL_SYS_TOKEN/.test(errorCode) || /FAIL_SYS_SESSION_EXPIRED|SESSION_EXPIRED/.test(errorMessage)) {\n            throw new AuthRequiredError('www.goofish.com', 'Xianyu search requires a logged-in browser session');\n        }\n        if (result?.error) {\n            throw new CommandExecutionError(errorMessage || `Xianyu search request failed: ${result.error}`);\n        }","sourceCodeStart":207,"sourceCodeEnd":243,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xianyu/search.js#L207-L243","documentation":"Xianyu (Goofish) search requires an authenticated browser session; the in-page script signals 'auth-required' when the mtop search call is rejected for lack of login, and the CLI converts this into an AuthRequiredError for www.goofish.com. The underlying mtop API refuses to serve search results to anonymous sessions.","triggerScenarios":"Running `xianyu search` while the managed browser session is logged out, the login cookie has expired, or the session was opened in an incognito/fresh profile.","commonSituations":"Cookies expiring after weeks of use, logging out of goofish.com manually, using a CI/headless environment with no logged-in profile, or a site-side session invalidation.","solutions":["Log in to www.goofish.com in the library's managed browser session, then retry","Re-run the library's login/auth flow command to refresh cookies","Clear stale session state and re-authenticate if the site keeps rejecting the session"],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// check login state before calling, e.g. via a session/profile check the library exposes\nconst loggedIn = await checkGoofishLogin();\nif (!loggedIn) await runLoginFlow();","typeGuard":null,"tryCatchPattern":"try { await xianyuSearch(args); } catch (e) { if (e instanceof AuthRequiredError) { await loginToGoofish(); return xianyuSearch(args); } throw e; }","preventionTips":["Keep the managed browser profile logged in to www.goofish.com","Re-run the login flow periodically before long automation runs","Detect AuthRequiredError and trigger re-auth automatically"],"tags":["authentication","session","browser","xianyu"],"backgroundTag":"auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}