{"record":{"id":"cbeefe1583afa02e","repo":"jackwener/OpenCLI","slug":"boss-geek-friend-enrichment-response-did-not-inclu","errorCode":null,"errorMessage":"Boss geek friend enrichment response did not include zpData.result","messagePattern":"Boss geek friend enrichment response did not include zpData\\.result","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/boss/utils.js","lineNumber":441,"sourceCode":"}\n/**\n * Enrich a batch of geek friends with full fields including securityId.\n * Processes in batches of 50 to avoid oversized request bodies.\n */\nexport async function fetchGeekFriendInfoList(page, friendIds = []) {\n    if (!friendIds.length) return [];\n    const BATCH_SIZE = 50;\n    const results = [];\n    for (let i = 0; i < friendIds.length; i += BATCH_SIZE) {\n        const batch = friendIds.slice(i, i + BATCH_SIZE).map(String);\n        const body = `friendIds=${batch.join(',')}`;\n        const data = await bossFetch(page, `https://${BOSS_DOMAIN}/wapi/zprelation/friend/getGeekFriendList.json`, {\n            method: 'POST',\n            body,\n        });\n        const batchResult = data.zpData?.result;\n        if (!Array.isArray(batchResult)) {\n            throw new CommandExecutionError('Boss geek friend enrichment response did not include zpData.result');\n        }\n        results.push(...batchResult);\n    }\n    return results;\n}\n/**\n * Find a geek-side friend by encrypted uid.\n * Merges label-list and enriched data; returns null if not found.\n */\nexport async function findGeekFriendByUid(page, encryptUid, opts = {}) {\n    const labelList = await fetchGeekFriendLabelList(page, { encryptSystemId: opts.encryptSystemId });\n    const candidate = labelList.find((f) => f.encryptFriendId === encryptUid ||\n        String(f.uid) === String(encryptUid) ||\n        String(f.friendId) === String(encryptUid));\n    if (!candidate) return null;\n    const enriched = await fetchGeekFriendInfoList(page, [candidate.friendId]);\n    return { ...candidate, ...(enriched[0] || {}) };\n}","sourceCodeStart":423,"sourceCodeEnd":459,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/boss/utils.js#L423-L459","documentation":"fetchGeekFriendInfoList enriches geek friends in batches of 50 via POST getGeekFriendList.json and expects each batch response to contain data.zpData.result as an array. A missing/non-array result means the batch response is an error envelope or the API schema changed, so the library throws instead of silently producing partial results.","triggerScenarios":"Calling the enriched command when a batch POST to getGeekFriendList.json returns without zpData.result — expired session, request body rejected (bad uid/securityId in batch), rate limiting, or field renamed by Boss.","commonSituations":"Long enrichment runs whose session expires mid-batch; friend list containing stale uids the endpoint rejects; anti-bot throttling during rapid batched POSTs; upstream schema change.","solutions":["Re-login and re-run the enriched command","Check the response data.code/body of the failing batch to identify auth vs throttling vs rejection","Reduce batch size or add delay between batches if throttled","Update the zpData.result path if Boss changed the response schema"],"exampleFix":"// before\nconst batchResult = data.zpData?.result;\nif (!Array.isArray(batchResult)) throw new CommandExecutionError('...');\n// after\nif (data.code !== 0) throw new AuthRequiredError(BOSS_DOMAIN, `getGeekFriendList code=${data.code}`);\nconst batchResult = data.zpData?.result ?? [];","handlingStrategy":"try-catch","validationCode":"// ensure the friend list source succeeded first\nconst friends = await fetchGeekFriendLabelList(page, { labelId, allowNonZero: false });\nif (!friends.length) return [];","typeGuard":"function hasBatchResult(d) { return Array.isArray(d?.zpData?.result); }","tryCatchPattern":"try { const enriched = await fetchGeekFriendInfoList(page, friends); }\ncatch (e) { if (e instanceof CommandExecutionError) { await relogin(page); return fetchGeekFriendInfoList(page, friends); } throw e; }","preventionTips":["Add a small delay between enrichment batches to avoid throttling","Refresh friend uids/securityIds before enriching stale lists","Check data.code per batch and abort-and-relogin on auth codes","Cap batch size below server limits"],"tags":["boss-zhipin","api-response","missing-field","batch"],"backgroundTag":"api-response-missing-field","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}