{"record":{"id":"0dfe96c7723d81ff","repo":"jackwener/OpenCLI","slug":"jike-notifications-api-returned-a-malformed-user","errorCode":null,"errorMessage":"Jike notifications API returned a malformed user","messagePattern":"Jike notifications API returned a malformed user","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/jike/notifications.js","lineNumber":64,"sourceCode":"}\n\nfunction mapNotification(notification) {\n    if (!notification || typeof notification !== 'object' || typeof notification.id !== 'string' || !notification.id) {\n        throw new CommandExecutionError('Jike notifications API returned a malformed notification');\n    }\n    if (typeof notification.type !== 'string' || !notification.type) {\n        throw new CommandExecutionError('Jike notifications API returned a notification without a type');\n    }\n    const actionItem = notification.actionItem;\n    if (!actionItem || typeof actionItem !== 'object' || Array.isArray(actionItem)) {\n        throw new CommandExecutionError('Jike notifications API returned a malformed action item');\n    }\n    if (!Array.isArray(actionItem.users)) {\n        throw new CommandExecutionError('Jike notifications API returned a malformed users list');\n    }\n    const names = actionItem.users.map((user) => {\n        if (!user || typeof user !== 'object') {\n            throw new CommandExecutionError('Jike notifications API returned a malformed user');\n        }\n        return typeof user.screenName === 'string' ? user.screenName : '';\n    }).filter(Boolean);\n    const referenceItem = notification.referenceItem;\n    const referenceContent = referenceItem && typeof referenceItem === 'object' && !Array.isArray(referenceItem)\n        ? referenceItem.content\n        : '';\n    const time = typeof notification.createdAt === 'string'\n        ? notification.createdAt\n        : (typeof notification.updatedAt === 'string' ? notification.updatedAt : '');\n    return {\n        type: resolveActionLabel(notification, actionItem),\n        user: names.join('、'),\n        content: cleanContent(actionItem.content || referenceContent),\n        time,\n    };\n}\n","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/jike/notifications.js#L46-L82","documentation":"mapNotification validates each entry of an action item's `users` array when building a notification row from the Jike notifications API. If any element is null or not a plain object, the library throws CommandExecutionError because it cannot extract a screen name from it. This is a defensive guard against the API returning a shape that changed or contains placeholder entries.","triggerScenarios":"The Jike notifications endpoint returns a notification whose actionItem.users array contains a null entry, a string/number instead of a user object, or the users field shape changes in a new API version while remaining an array.","commonSituations":"Jike changes its notification payload schema; deleted/suspended users appear as null placeholders in action lists; a proxy or cached response truncates/mangles user objects; running an older CLI against a newer API version.","solutions":["Log the raw notification JSON to identify which notification and which user entry is malformed","Update the CLI/library to the latest version to pick up any schema compatibility fixes","Patch the mapping code to skip or coalesce malformed user entries instead of throwing","Retry later in case it was a transient server-side data issue; report to Jike if persistent"],"exampleFix":"// before\nconst names = actionItem.users.map((user) => {\n  if (!user || typeof user !== 'object') {\n    throw new CommandExecutionError('Jike notifications API returned a malformed user');\n  }\n  return typeof user.screenName === 'string' ? user.screenName : '';\n}).filter(Boolean);\n// after\nconst names = actionItem.users.map((user) =>\n  user && typeof user === 'object' && typeof user.screenName === 'string' ? user.screenName : ''\n).filter(Boolean);","handlingStrategy":"type-guard","validationCode":"// pre-validate a notifications response before mapping\nfunction hasValidUserArrays(body) {\n  return Array.isArray(body?.data) && body.data.every((n) =>\n    !n?.actionItem || n.actionItem == null || Array.isArray(n.actionItem.users));\n}","typeGuard":"function isUser(u) {\n  return u !== null && typeof u === 'object' && !Array.isArray(u);\n}","tryCatchPattern":"try {\n  const rows = await cli('jike', 'notifications').run();\n} catch (e) {\n  if (String(e.message).includes('malformed user')) {\n    // fall back to raw API fetch and lenient manual mapping\n  } else throw e;\n}","preventionTips":["Keep the CLI updated against Jike API schema changes","Log raw notification payloads when mapping failures occur","Prefer lenient mapping (skip bad entries) in your own wrapper before invoking the CLI"],"tags":["api-response","schema-validation","jike"],"backgroundTag":"schema-validation-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}