jackwener/OpenCLI · error · CommandExecutionError

Boss recruiter history response did not include a message li

Error message

Boss recruiter history response did not include a message list

What it means

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.

Source

Thrown at clis/boss/chatmsg.js:49

        from: isFromBoss ? '对方' : '我',
        type: TYPE_MAP[m.type] || `其他(${m.type})`,
        text: m.text || m.body?.text || m.body?.content || m.body?.showText ||
            JSON.stringify(m.body || {}).slice(0, 120),
        time: m.time ? new Date(m.time).toLocaleString('zh-CN') : '',
    };
}

async function bossChatMsg(page, kwargs, existingFriend) {
    const friend = existingFriend ?? await findFriendByUid(page, kwargs.uid);
    if (!friend) throw new EmptyResultError('boss chatmsg', '未找到该候选人');
    if (!friend.securityId) throw new CommandExecutionError('该聊天缺少 securityId,无法获取历史消息');
    const gid = friend.uid;
    const securityId = encodeURIComponent(friend.securityId);
    const msgUrl = `https://www.zhipin.com/wapi/zpchat/boss/historyMsg?gid=${gid}&securityId=${securityId}&page=${kwargs.page}&c=20&src=0`;
    const msgData = await bossFetch(page, msgUrl);
    const messages = msgData.zpData?.messages ?? msgData.zpData?.historyMsgList;
    if (!Array.isArray(messages)) {
        throw new CommandExecutionError('Boss recruiter history response did not include a message list');
    }
    if (messages.length === 0) {
        throw new EmptyResultError('boss chatmsg', 'Boss returned no messages for this chat.');
    }
    return messages.map((m) => mapBossMsg(m, friend));
}

async function geekChatMsg(page, kwargs, encryptSystemId) {
    const friend = await findGeekFriendByUid(page, kwargs.uid, { encryptSystemId });
    if (!friend) throw new EmptyResultError('boss chatmsg', '未找到该聊天(geek 侧)');
    if (!friend.securityId) throw new CommandExecutionError('该聊天缺少 securityId,无法获取历史消息');
    const messages = await fetchGeekHistoryMsg(page, friend, { page: kwargs.page });
    return messages.map((m) => mapGeekMsg(m, friend));
}

cli({
    site: 'boss',
    name: 'chatmsg',

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Re-login / refresh the BOSS session cookies — an expired session often yields error envelopes without a message list.
  2. Retry with page=1; some API versions reject or return odd shapes for deep pagination pages.
  3. Enable verbose logging and inspect the raw zpData to see what fields are actually returned (check for a renamed messages field).
  4. If BOSS renamed the field, update the extraction (msgData.zpData?.messages ?? msgData.zpData?.historyMsgList) in clis/boss/chatmsg.js or upgrade the CLI package.
  5. Try the geek side (side=geek) which uses a different history endpoint.

Example fix

// before
const messages = msgData.zpData?.messages ?? msgData.zpData?.historyMsgList;
// after — also recognize newer field name and error envelopes
const messages = msgData.zpData?.messages ?? msgData.zpData?.historyMsgList ?? msgData.zpData?.msgList;
if (!Array.isArray(messages)) throw new CommandExecutionError(`Unexpected historyMsg payload: ${JSON.stringify(msgData).slice(0,200)}`);
Defensive patterns

Strategy: try-catch

Validate before calling

// check session health before batch-fetching history
const ok = await chatlist({}); // a successful authenticated list read implies a live session
if (!ok.length) throw new Error('session may be logged out');

Type guard

function isMessageArray(v) { return Array.isArray(v) && v.every(m => m && typeof m === 'object'); }

Try / catch

try {
  const msgs = await chatmsg(uid, { page: 1 });
} catch (e) {
  if (isCommandExecutionError(e) && /message list/.test(e.message)) {
    await relogin(); // likely an error envelope from an expired session
    return chatmsg(uid, { page: 1 });
  }
  throw e;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29). Data as JSON: /api/errors/e59d01d07d3be2f4. Report an issue: GitHub.