jackwener/OpenCLI · error · CommandExecutionError

Bilibili comments reply ${index + 1} was malformed

Error message

Bilibili comments reply ${index + 1} was malformed

What it means

Thrown by formatReplyRow when an entry in the replies array is null, not an object, or an array — i.e. it cannot be formatted as a comment row. The CLI treats each reply as a structured object (rpid, ctime, member, content) and rejects anything else rather than emitting a broken row.

Source

Thrown at clis/bilibili/comments.js:81

    return data.replies;
}

function requireTopReplies(data, label) {
    if (!data || typeof data !== 'object' || Array.isArray(data)) {
        throw new CommandExecutionError(`Bilibili ${label} API returned malformed data`);
    }
    if (!Object.hasOwn(data, 'top_replies')) {
        throw new CommandExecutionError(`Bilibili ${label} API did not return top_replies`);
    }
    if (!Array.isArray(data.top_replies)) {
        throw new CommandExecutionError(`Bilibili ${label} API returned malformed top_replies`);
    }
    return data.top_replies;
}

function formatReplyRow(reply, index) {
    if (!reply || typeof reply !== 'object' || Array.isArray(reply)) {
        throw new CommandExecutionError(`Bilibili comments reply ${index + 1} was malformed`);
    }
    const rpid = String(reply.rpid ?? '').trim();
    if (!rpid) {
        throw new CommandExecutionError(`Bilibili comments reply ${index + 1} was missing rpid`);
    }
    const ctime = Number(reply.ctime);
    if (!Number.isFinite(ctime)) {
        throw new CommandExecutionError(`Bilibili comments reply ${index + 1} was missing ctime`);
    }
    return {
        rank: index + 1,
        rpid,
        author: String(reply.member?.uname ?? ''),
        text: String(reply.content?.message ?? '').replace(/\n/g, ' ').trim(),
        likes: reply.like ?? 0,
        replies: reply.rcount ?? 0,
        time: new Date(ctime * 1000).toISOString().slice(0, 16).replace('T', ' '),
    };

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Retry the command — null entries are often transient from comment moderation
  2. Drop --limit or paginate differently to avoid the problematic page
  3. Filter non-object replies before formatting (or update the library version)
  4. Report the video/rpid upstream if the API consistently returns malformed entries

Example fix

// before
return replies.slice(0, limit).map(formatReplyRow);
// after
return replies.slice(0, limit)
    .filter((r) => r && typeof r === 'object' && !Array.isArray(r))
    .map(formatReplyRow);
Defensive patterns

Strategy: type-guard

Validate before calling

const badIndex = replies.findIndex((r) => !r || typeof r !== 'object' || Array.isArray(r));
if (badIndex !== -1) console.warn(`reply at index ${badIndex} is not an object`);

Type guard

function isReplyObject(reply) {
    return !!reply && typeof reply === 'object' && !Array.isArray(reply);
}

Try / catch

try {
    const rows = await bilibiliComments(bvid);
} catch (err) {
    if (/reply \d+ was malformed/.test(err.message)) {
        // retry or treat as partial data
    } else throw err;
}

Prevention

When it happens

Trigger: Calling 'bilibili comments <bvid>' (or with --parent/--top) where the API returns a replies/top_replies array containing null or non-object elements at position index+1.

Common situations: Bilibili occasionally returns null entries inside reply lists for deleted/filtered comments; scraped or proxied responses with sanitized/emptied items; upstream schema drift.

Understand the failure class

Related errors


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