{"record":{"id":"9c5235a43ae5f841","repo":"jackwener/OpenCLI","slug":"xianyu-publish-form-was-not-detected","errorCode":null,"errorMessage":"Xianyu publish form was not detected","messagePattern":"Xianyu publish form was not detected","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xianyu/publish.js","lineNumber":399,"sourceCode":"        { name: 'category', required: true, positional: true, help: '商品分类关键词（如：手机、衣服、图书）' },\n        { name: 'original_price', type: 'float', help: '原价（选填，用于显示折扣）' },\n        { name: 'location', help: '所在地区（选填，如：杭州）' },\n        { name: 'images', help: '本地图片路径，多张用逗号分隔（选填，如：/tmp/a.jpg,/tmp/b.jpg）' },\n    ],\n    columns: ['status', 'item_id', 'title', 'price', 'condition', 'url', 'message'],\n    func: async (page, kwargs) => {\n        const data = normalizePublishArgs(kwargs);\n        // 1. 导航到发布页\n        await page.goto(buildPublishUrl());\n        await page.wait(3);\n\n        // 2. 检查登录状态\n        const initState = await page.evaluate(buildExtractPageStateEvaluate());\n        if (initState?.requiresAuth) {\n            throw new AuthRequiredError('www.goofish.com', '发布闲鱼需要先登录，请在 Chrome 中打开 goofish.com 并完成登录');\n        }\n        if (!initState?.hasPublishForm) {\n            throw new CommandExecutionError('Xianyu publish form was not detected', 'Confirm goofish.com is logged in and the publish page finished loading.');\n        }\n\n        // 3. 选择分类（先于其他字段，因为分类可能影响表单结构）\n        const categoryResult = await page.evaluate(buildSelectCategoryEvaluate(data.category));\n        if (!categoryResult?.ok) {\n            throw new CommandExecutionError(`Xianyu category selection failed: ${categoryResult?.reason || 'unknown-reason'}`);\n        }\n        await page.wait(1.5);\n\n        // 4. 填充表单\n        const fillResult = await page.evaluate(buildFillFormEvaluate(data));\n        if (!fillResult?.ok) {\n            const missing = Array.isArray(fillResult?.missing) ? fillResult.missing.join(', ') : 'unknown';\n            throw new CommandExecutionError(`Xianyu publish form fill failed; missing fields: ${missing}`);\n        }\n        await page.wait(1);\n\n        // 5. 上传图片（如果有）","sourceCodeStart":381,"sourceCodeEnd":417,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xianyu/publish.js#L381-L417","documentation":"After the auth check, the flow verifies the publish form is present via buildExtractPageStateEvaluate(); if initState.hasPublishForm is falsy it throws CommandExecutionError('Xianyu publish form was not detected'). The page loaded and you are logged in, but the expected form elements were not found in the DOM.","triggerScenarios":"page.goto(buildPublishUrl()) lands on a page where buildExtractPageStateEvaluate returns no hasPublishForm: redirect off the publish route, page still loading when state is extracted, redesigned DOM, or a bot-check/interstitial page.","commonSituations":"Slow networks where the SPA hasn't rendered form fields when evaluate runs, goofish frontend redesign, region/language redirects, or anti-bot verification pages.","solutions":["Increase the wait before evaluating page state (the flow waits page.wait(3) — raise it on slow networks)","Manually open the publish URL in the same Chrome profile to confirm the form renders","Update the library if goofish changed its DOM (selectors in buildExtractPageStateEvaluate are stale)","Complete any anti-bot/verification interstitial in the browser first"],"exampleFix":"// before\nawait page.goto(buildPublishUrl());\nawait page.wait(3);\n// after\nawait page.goto(buildPublishUrl());\nawait page.wait(8); // allow SPA to finish rendering on slow networks","handlingStrategy":"retry","validationCode":"const state = await page.evaluate(buildExtractPageStateEvaluate());\nif (!state?.hasPublishForm) {\n  throw new Error('Publish form not rendered yet; increase wait or check the URL');\n}","typeGuard":"function hasPublishForm(state) {\n  return Boolean(state && state.hasPublishForm === true);\n}","tryCatchPattern":"try {\n  await publish(data);\n} catch (e) {\n  if (e instanceof CommandExecutionError && /publish form was not detected/.test(e.message)) {\n    await sleep(3000);\n    await publish(data);\n  } else throw e;\n}","preventionTips":["Add generous waits on slow networks before reading page state","Confirm the publish URL renders in the same Chrome profile manually","Keep the library updated when goofish changes its frontend"],"tags":["browser-automation","dom","page-load"],"backgroundTag":"page-not-loaded","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}