jackwener/OpenCLI · error · CommandExecutionError
Jike notifications API returned a malformed notification
Error message
Jike notifications API returned a malformed notification
What it means
CommandExecutionError thrown by mapNotification in clis/jike/notifications.js when a notification object from the Jike notifications API lacks a valid id. mapNotification requires each item to be a non-null object with a non-empty string id before it can be mapped into an output row; anything else is treated as a malformed API response rather than being silently skipped.
Source
Thrown at clis/jike/notifications.js:50
if (typeof TYPE_LABELS[notification.type] === 'string') return TYPE_LABELS[notification.type];
if (typeof actionItem.behavior === 'string' && actionItem.behavior.trim()) return actionItem.behavior.trim();
const sourceType = String(actionItem.type || notification.actionType || notification.type || '').toUpperCase();
if (sourceType.includes('LIKE')) return '赞了你';
if (sourceType.includes('COMMENT')) return '评论了你';
if (sourceType.includes('FOLLOW')) return '关注了你';
if (sourceType.includes('REPOST')) return '转发了你';
if (sourceType.includes('MENTION')) return '提到了你';
if (sourceType.includes('REPLY')) return '回复了你';
return notification.type;
}
function cleanContent(value) {
return typeof value === 'string' ? value.replace(/\n/g, ' ').slice(0, 100) : '';
}
function mapNotification(notification) {
if (!notification || typeof notification !== 'object' || typeof notification.id !== 'string' || !notification.id) {
throw new CommandExecutionError('Jike notifications API returned a malformed notification');
}
if (typeof notification.type !== 'string' || !notification.type) {
throw new CommandExecutionError('Jike notifications API returned a notification without a type');
}
const actionItem = notification.actionItem;
if (!actionItem || typeof actionItem !== 'object' || Array.isArray(actionItem)) {
throw new CommandExecutionError('Jike notifications API returned a malformed action item');
}
if (!Array.isArray(actionItem.users)) {
throw new CommandExecutionError('Jike notifications API returned a malformed users list');
}
const names = actionItem.users.map((user) => {
if (!user || typeof user !== 'object') {
throw new CommandExecutionError('Jike notifications API returned a malformed user');
}
return typeof user.screenName === 'string' ? user.screenName : '';
}).filter(Boolean);
const referenceItem = notification.referenceItem;View on GitHub (pinned to 49907e53dc)
Solutions
- Retry the command — if transient, a fresh fetch may return well-formed items
- Reduce --limit or paginate differently to see whether a specific page contains the malformed item
- Capture the raw /1.0/notifications/list response body and inspect the offending entry's shape
- If Jike changed the contract, relax the check in mapNotification to skip items without id (filter) instead of throwing, or map the new shape
- Report/patch: replace the throw with `if (!valid) return null;` and filter nulls in listNotifications
Example fix
// before
if (!notification || typeof notification !== 'object' || typeof notification.id !== 'string' || !notification.id) {
throw new CommandExecutionError('Jike notifications API returned a malformed notification');
}
// after: skip malformed entries instead of failing the whole command
function mapNotification(notification) {
if (!notification || typeof notification !== 'object' || typeof notification.id !== 'string' || !notification.id) {
return null;
}
...
}
const rows = body.data.map(mapNotification).filter(Boolean); Defensive patterns
Strategy: type-guard
Validate before calling
function isValidNotification(n) {
return n != null && typeof n === 'object' && typeof n.id === 'string' && n.id.length > 0;
}
const usable = body.data.filter(isValidNotification); // pre-filter before mapping Type guard
function hasNotificationId(n) {
return typeof n === 'object' && n !== null && typeof n.id === 'string' && n.id !== '';
} Try / catch
try {
rows = await jikeNotifications(page, limit);
} catch (e) {
if (/malformed notification$/.test(e.message)) {
// refetch once; if it persists, the API contract changed — fall back to raw items
rows = (await fetchRaw()).filter(hasNotificationId);
} else throw e;
} Prevention
- Filter raw API items through an id validity check before mapping
- Pin and monitor the Jike notifications API response shape in tests
- Log and skip (rather than crash on) single malformed items in your own wrappers
- Watch for Jike API changelog updates that introduce new item kinds
When it happens
Trigger: Calling the jike notifications command when the /1.0/notifications/list response contains an entry that is null, not an object, or has a missing/empty/non-string id field.
Common situations: Jike API contract change introducing new item shapes (e.g. deleted-content placeholders with no id); undocumented item types in the feed; partial/edge-case notifications (recalled content) serialized differently; API returning test/error entries inside data array.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- Jike notifications API returned a notification without a typ
- Jike notifications API returned a malformed action item
- Jike notifications API returned a malformed users list
- Bilibili creator comparison API returned malformed list data
- Bilibili creator comparison returned a malformed manuscript
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/fb5eb5f258e427c8.
Report an issue: GitHub.