{"record":{"id":"599c2b10a73eb0bc","repo":"jackwener/OpenCLI","slug":"xianyu-publish-form-fill-failed-missing-fields","errorCode":null,"errorMessage":"Xianyu publish form fill failed; missing fields: ${missing}","messagePattern":"Xianyu publish form fill failed; missing fields: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xianyu/publish.js","lineNumber":413,"sourceCode":"        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. 上传图片（如果有）\n        if (data.images.length > 0) {\n            if (!page.setFileInput) {\n                throw new CommandExecutionError('Xianyu publish requires Browser Bridge file upload support', 'Use a browser mode that supports setFileInput.');\n            }\n            const fileInput = await page.evaluate(buildFindFileInputSelectorEvaluate());\n            if (!fileInput?.ok) {\n                throw new CommandExecutionError(`Xianyu image upload input was not found: ${fileInput?.reason || 'unknown-reason'}`);\n            }\n            try {\n                await page.setFileInput(data.images, fileInput.selector || 'input[type=\"file\"]');\n                await page.wait(3); // 等待图片上传处理\n            } catch (err) {\n                throw new CommandExecutionError(`Xianyu image upload failed: ${err?.message || err}`);\n            }","sourceCodeStart":395,"sourceCodeEnd":431,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xianyu/publish.js#L395-L431","documentation":"After buildFillFormEvaluate(data) runs in the page, a falsy ok result throws CommandExecutionError listing the missing fields (fillResult.missing joined, or 'unknown'). It means one or more form fields (title/description/price/etc.) could not be filled on the goofish publish form.","triggerScenarios":"buildFillFormEvaluate returns { ok: false, missing: [...] } when inputs for specific fields are absent from the DOM or could not receive values — missing title/description/price inputs, changed selectors, or fields disabled until other steps complete.","commonSituations":"goofish frontend redesign renaming input elements, page not fully rendered before fill, required fields conditionally shown, or values rejected by the form's own validation leaving them 'missing'.","solutions":["Check the listed missing field names and confirm the corresponding data values are non-empty and valid","Increase the wait before filling so all inputs are mounted","Retry once — transient render timing often resolves on a second run","Update buildFillFormEvaluate selectors to match the current goofish DOM"],"exampleFix":"// before\nawait publish({ title: '', description: 'desc', price: '10' });\n// after\nawait publish({ title: 'iPhone 13 128G', description: 'desc', price: '10' });","handlingStrategy":"try-catch","validationCode":"for (const f of ['title', 'description', 'price']) {\n  if (data[f] == null || String(data[f]).trim() === '') {\n    throw new Error(`Field \"${f}\" is required before publish`);\n  }\n}","typeGuard":"function isFillableListing(d) {\n  return Boolean(d && typeof d.title === 'string' && d.title.trim()\n    && typeof d.description === 'string' && d.description.trim()\n    && d.price != null);\n}","tryCatchPattern":"try {\n  await publish(data);\n} catch (e) {\n  if (e instanceof CommandExecutionError && /form fill failed/.test(e.message)) {\n    const missing = e.message.match(/fields: (.+)$/)?.[1] ?? 'unknown';\n    console.error(`Refill needed for: ${missing}`);\n    await sleep(2000);\n    await publish(data);\n  } else throw e;\n}","preventionTips":["Ensure all required listing fields are non-empty before publishing","Log fillResult.missing to target exactly which fields the DOM lacked","Wait for the form to fully mount before filling; retry once on transient render timing"],"tags":["browser-automation","dom","form-fill"],"backgroundTag":"dom-selector-mismatch","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}