{"record":{"id":"c98a798f9728022b","repo":"jackwener/OpenCLI","slug":"bilibili-label-api-returned-malformed-top-repli","errorCode":null,"errorMessage":"Bilibili ${label} API returned malformed top_replies","messagePattern":"Bilibili (.+?) API returned malformed top_replies","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/bilibili/comments.js","lineNumber":74,"sourceCode":"    }\n    if (data.replies === null) {\n        return [];\n    }\n    if (!Array.isArray(data.replies)) {\n        throw new CommandExecutionError(`Bilibili ${label} API returned malformed replies`);\n    }\n    return data.replies;\n}\n\nfunction requireTopReplies(data, label) {\n    if (!data || typeof data !== 'object' || Array.isArray(data)) {\n        throw new CommandExecutionError(`Bilibili ${label} API returned malformed data`);\n    }\n    if (!Object.hasOwn(data, 'top_replies')) {\n        throw new CommandExecutionError(`Bilibili ${label} API did not return top_replies`);\n    }\n    if (!Array.isArray(data.top_replies)) {\n        throw new CommandExecutionError(`Bilibili ${label} API returned malformed top_replies`);\n    }\n    return data.top_replies;\n}\n\nfunction formatReplyRow(reply, index) {\n    if (!reply || typeof reply !== 'object' || Array.isArray(reply)) {\n        throw new CommandExecutionError(`Bilibili comments reply ${index + 1} was malformed`);\n    }\n    const rpid = String(reply.rpid ?? '').trim();\n    if (!rpid) {\n        throw new CommandExecutionError(`Bilibili comments reply ${index + 1} was missing rpid`);\n    }\n    const ctime = Number(reply.ctime);\n    if (!Number.isFinite(ctime)) {\n        throw new CommandExecutionError(`Bilibili comments reply ${index + 1} was missing ctime`);\n    }\n    return {\n        rank: index + 1,","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/bilibili/comments.js#L56-L92","documentation":"This CommandExecutionError is thrown by requireTopReplies when the Bilibili /x/v2/reply/main API response contains a top_replies field that is present but not an array (checked after verifying the field exists). It indicates the pinned-comments payload shape deviates from what the CLI expects, so it refuses to iterate over it. It guards against API schema changes or corrupted responses.","triggerScenarios":"Running 'bilibili comments <bvid> --top' where the API's data object has top_replies set to a non-array value (e.g. an object, number, or string) instead of a list of pinned comments.","commonSituations":"Bilibili changes the reply-main schema for pinned comments; a proxy/interceptor returns rewritten JSON; edge cases where the API emits top_replies as null-like or object forms for videos with unusual pinning state.","solutions":["Drop --top and fetch normal comments to check whether only the pinned path is affected","Retry later — a transient/changed upstream schema may self-correct or be fixed in a CLI update","Update the CLI/library to the latest version that tracks current Bilibili reply-main schema","Inspect the raw API payload (data.top_replies) to confirm the shape and file an issue if the schema changed"],"exampleFix":"// before\nif (!Array.isArray(data.top_replies)) {\n    throw new CommandExecutionError(`Bilibili ${label} API returned malformed top_replies`);\n}\n// after\n// tolerate null as 'no pinned comments'\nconst tops = data.top_replies === null ? [] : data.top_replies;\nif (!Array.isArray(tops)) {\n    throw new CommandExecutionError(`Bilibili ${label} API returned malformed top_replies`);\n}","handlingStrategy":"type-guard","validationCode":"const data = payload?.data;\nif (data && Array.isArray(data.top_replies)) {\n    // safe to proceed with --top\n}","typeGuard":"function isTopRepliesArray(data) {\n    return !!data && typeof data === 'object' && Array.isArray(data.top_replies);\n}","tryCatchPattern":"try {\n    const rows = await bilibiliComments(bvid, { top: true });\n} catch (err) {\n    if (/malformed top_replies/.test(err.message)) {\n        // fall back to non-pinned comments or skip this video\n    } else throw err;\n}","preventionTips":["Keep the CLI updated for Bilibili schema changes","Validate payload shape before relying on --top","Fallback to normal comments when the pinned path fails","Log raw response bodies to diagnose upstream drift"],"tags":["bilibili","api-schema","validation"],"backgroundTag":"unexpected-api-response-shape","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}