{"record":{"id":"d64d1c69fa8deb65","repo":"jackwener/OpenCLI","slug":"xianyu-reply-requires-a-logged-in-browser-session","errorCode":null,"errorMessage":"Xianyu reply requires a logged-in browser session","messagePattern":"Xianyu reply requires a logged-in browser session","errorType":"exception","errorClass":"AuthRequiredError","httpStatus":null,"severity":"error","filePath":"clis/xianyu/reply.js","lineNumber":54,"sourceCode":"        const itemId = hasIds ? normalizeNumericId(kwargs.item_id, 'item_id', '1038951278192') : '';\n        const userId = hasIds ? normalizeNumericId(kwargs.user_id, 'user_id', '3650092411') : '';\n        const text = requireText(kwargs.text, 'xianyu reply --text');\n        const url = hasIds ? buildChatUrl(itemId, userId) : '';\n        if (hasIds) {\n            await page.goto(url);\n        } else {\n            if (!page.getCurrentUrl || !/https:\\/\\/www\\.goofish\\.com\\/im\\b/.test(await page.getCurrentUrl())) {\n                await page.goto('https://www.goofish.com/im');\n            }\n        }\n        await page.wait(2);\n        if (rank > 0) {\n            requireClickResult(await page.evaluate(buildClickInboxConversationEvaluate(rank - 1)), 'reply rank click');\n            await page.wait(2);\n        }\n        const state = requireEvaluateObject(await page.evaluate(buildExtractChatStateEvaluate()), 'reply');\n        if (state?.requiresAuth) {\n            throw new AuthRequiredError('www.goofish.com', 'Xianyu reply requires a logged-in browser session');\n        }\n        if (!state?.can_input) {\n            throw selectorError('闲鱼聊天输入框', '未找到可用的聊天输入框，请确认该会话页已正确加载');\n        }\n        const sent = requireEvaluateObject(await page.evaluate(buildSendMessageEvaluate(text)), 'reply send');\n        if (!sent?.ok) {\n            throw new CommandExecutionError(`Xianyu reply did not observe the sent message: ${sent?.reason || 'unknown-reason'}`);\n        }\n        await page.wait(1);\n        return [{\n            status: 'sent',\n            peer_name: state.peer_name || '',\n            item_title: state.item_title || '',\n            price: state.price || '',\n            location: state.location || '',\n            message: text,\n            peer_user_id: userId,\n            item_id: itemId,","sourceCodeStart":36,"sourceCodeEnd":72,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xianyu/reply.js#L36-L72","documentation":"After loading the chat page, reply extracts chat state via buildExtractChatStateEvaluate(); if the page reports requiresAuth, the CLI throws AuthRequiredError for www.goofish.com. Goofish chat requires a logged-in session, and the injected cookie/browser session is not authenticated.","triggerScenarios":"`xianyu reply` (IDs or --rank mode) where the extracted state has requiresAuth true — expired goofish login cookies, navigating before login, or the session was logged out / invalidated server-side.","commonSituations":"Cookie-based (Strategy.COOKIE) sessions expiring after goofish rotates tokens; running headless with stale cookie files; goofish forcing re-login after risk-control detection; never having logged in on the browser profile used.","solutions":["Re-login to www.goofish.com in the browser/Browser Bridge profile and refresh stored cookies, then retry.","Refresh the cookie file used by Strategy.COOKIE with cookies exported from a logged-in session.","If risk-control logged you out, complete verification in a visible browser before retrying headless."],"exampleFix":"// before: stale cookies\nawait opencli.run('xianyu', 'reply', { item_id, user_id, text });\n// after: re-import fresh cookies after re-login\nawait importCookiesFromBrowser('www.goofish.com', 'cookies.json');\nawait opencli.run('xianyu', 'reply', { item_id, user_id, text });","handlingStrategy":"try-catch","validationCode":"// verify the goofish session is logged in before replying\nconst loggedIn = await page.evaluate(() => !document.querySelector('[class*=\"login\"], .login-dialog') && !!document.cookie.includes('unb'));\nif (!loggedIn) throw new Error('Goofish session expired; re-login before replying.');","typeGuard":null,"tryCatchPattern":"try {\n  return await reply(kwargs);\n} catch (e) {\n  if (e.name === 'AuthRequiredError' || String(e.message).includes('logged-in browser session')) {\n    await refreshGoofishSession(); // re-login / re-import cookies\n    return reply(kwargs); // retry once with fresh session\n  }\n  throw e;\n}","preventionTips":["Refresh goofish cookies regularly; sessions expire and rotate tokens.","Run a cheap authenticated read (e.g. xianyu inbox) to probe session health before writes.","Complete any risk-control verification in a visible browser before headless runs.","Keep a stable logged-in browser profile dedicated to automation."],"tags":["authentication","session-expired","cookies","xianyu"],"backgroundTag":"auth-required","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}