{"record":{"id":"e59d01d07d3be2f4","repo":"jackwener/OpenCLI","slug":"boss-recruiter-history-response-did-not-include-a","errorCode":null,"errorMessage":"Boss recruiter history response did not include a message list","messagePattern":"Boss recruiter history response did not include a message list","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/boss/chatmsg.js","lineNumber":49,"sourceCode":"        from: isFromBoss ? '对方' : '我',\n        type: TYPE_MAP[m.type] || `其他(${m.type})`,\n        text: m.text || m.body?.text || m.body?.content || m.body?.showText ||\n            JSON.stringify(m.body || {}).slice(0, 120),\n        time: m.time ? new Date(m.time).toLocaleString('zh-CN') : '',\n    };\n}\n\nasync function bossChatMsg(page, kwargs, existingFriend) {\n    const friend = existingFriend ?? await findFriendByUid(page, kwargs.uid);\n    if (!friend) throw new EmptyResultError('boss chatmsg', '未找到该候选人');\n    if (!friend.securityId) throw new CommandExecutionError('该聊天缺少 securityId，无法获取历史消息');\n    const gid = friend.uid;\n    const securityId = encodeURIComponent(friend.securityId);\n    const msgUrl = `https://www.zhipin.com/wapi/zpchat/boss/historyMsg?gid=${gid}&securityId=${securityId}&page=${kwargs.page}&c=20&src=0`;\n    const msgData = await bossFetch(page, msgUrl);\n    const messages = msgData.zpData?.messages ?? msgData.zpData?.historyMsgList;\n    if (!Array.isArray(messages)) {\n        throw new CommandExecutionError('Boss recruiter history response did not include a message list');\n    }\n    if (messages.length === 0) {\n        throw new EmptyResultError('boss chatmsg', 'Boss returned no messages for this chat.');\n    }\n    return messages.map((m) => mapBossMsg(m, friend));\n}\n\nasync function geekChatMsg(page, kwargs, encryptSystemId) {\n    const friend = await findGeekFriendByUid(page, kwargs.uid, { encryptSystemId });\n    if (!friend) throw new EmptyResultError('boss chatmsg', '未找到该聊天（geek 侧）');\n    if (!friend.securityId) throw new CommandExecutionError('该聊天缺少 securityId，无法获取历史消息');\n    const messages = await fetchGeekHistoryMsg(page, friend, { page: kwargs.page });\n    return messages.map((m) => mapGeekMsg(m, friend));\n}\n\ncli({\n    site: 'boss',\n    name: 'chatmsg',","sourceCodeStart":31,"sourceCodeEnd":67,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/boss/chatmsg.js#L31-L67","documentation":"bossChatMsg throws CommandExecutionError('Boss recruiter history response did not include a message list') when the /wapi/zpchat/boss/historyMsg API responds but zpData contains neither `messages` nor `historyMsgList` arrays. The library treats this as a server-side response-shape failure: the request succeeded mechanically but the expected payload is absent, usually indicating an API contract change or an error body.","triggerScenarios":"bossFetch returns a zhpData payload where zpData.messages and zpData.historyMsgList are both undefined — e.g. BOSS returns zpData as an error object, an HTML login page was fetched instead of JSON, or BOSS renamed the messages field.","commonSituations":"Session expired so the endpoint returns an error envelope without zpData.messages; BOSS API version bump renaming the field; anti-bot interstitial served instead of JSON; passing an out-of-range --page value the API rejects silently.","solutions":["Re-login / refresh the BOSS session cookies — an expired session often yields error envelopes without a message list.","Retry with page=1; some API versions reject or return odd shapes for deep pagination pages.","Enable verbose logging and inspect the raw zpData to see what fields are actually returned (check for a renamed messages field).","If BOSS renamed the field, update the extraction (msgData.zpData?.messages ?? msgData.zpData?.historyMsgList) in clis/boss/chatmsg.js or upgrade the CLI package.","Try the geek side (side=geek) which uses a different history endpoint."],"exampleFix":"// before\nconst messages = msgData.zpData?.messages ?? msgData.zpData?.historyMsgList;\n// after — also recognize newer field name and error envelopes\nconst messages = msgData.zpData?.messages ?? msgData.zpData?.historyMsgList ?? msgData.zpData?.msgList;\nif (!Array.isArray(messages)) throw new CommandExecutionError(`Unexpected historyMsg payload: ${JSON.stringify(msgData).slice(0,200)}`);","handlingStrategy":"try-catch","validationCode":"// check session health before batch-fetching history\nconst ok = await chatlist({}); // a successful authenticated list read implies a live session\nif (!ok.length) throw new Error('session may be logged out');","typeGuard":"function isMessageArray(v) { return Array.isArray(v) && v.every(m => m && typeof m === 'object'); }","tryCatchPattern":"try {\n  const msgs = await chatmsg(uid, { page: 1 });\n} catch (e) {\n  if (isCommandExecutionError(e) && /message list/.test(e.message)) {\n    await relogin(); // likely an error envelope from an expired session\n    return chatmsg(uid, { page: 1 });\n  }\n  throw e;\n}","preventionTips":["Refresh session cookies periodically; expired sessions yield error envelopes without messages.","Start pagination at page=1 and stop on empty results.","Upgrade the package when BOSS changes the wapi response shape.","Inspect raw zpData via verbose mode before filing issues."],"tags":["boss-zhipin","api-response-shape","wapi","command-execution-error"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}