jackwener/OpenCLI · error · CommandExecutionError

${commandName}: malformed comment row ${field}

Error message

${commandName}: malformed comment row ${field}

What it means

normalizeOptionalString validates that a comment row field (e.g. text) coming from the page scrape is a string or null. Any non-string, non-null value means the comment row shape is unexpected, so a CommandExecutionError is thrown naming the field.

Source

Thrown at clis/xiaohongshu/comments.js:71

        return 0;
    if (integerRe.test(raw))
        return Number(raw.replace(/[,+,]/g, ''));
    const short = raw.match(shortformRe);
    if (!short)
        return 0;
    const numeric = Number(short[1].replace(/[,,]/g, ''));
    if (!Number.isFinite(numeric))
        return 0;
    const unit = short[2].toLowerCase();
    const multiplier = unit === 'w' || unit === '万' ? 10000 : 1000;
    return Math.round(numeric * multiplier);
}

function normalizeOptionalString(value, field, commandName) {
    if (value == null)
        return '';
    if (typeof value !== 'string') {
        throw new CommandExecutionError(`${commandName}: malformed comment row ${field}`);
    }
    return value;
}

export function normalizeCommentImages(value, commandName) {
    if (value == null)
        return [];
    if (!Array.isArray(value)) {
        throw new CommandExecutionError(`${commandName}: malformed comment row images`);
    }
    const urls = [];
    for (const raw of value) {
        if (typeof raw !== 'string') {
            throw new CommandExecutionError(`${commandName}: malformed comment row image URL`);
        }
        const trimmed = raw.trim();
        let parsed;
        try {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the offending comment row to inspect the actual field type.
  2. Update the normalizer to coerce or handle the new shape (e.g. text as { content: ... } object).
  3. Pre-validate scraped rows with a schema check before calling the comments API.
  4. Pin/rollback to a library version matching the current XHS page format if this is a regression.

Example fix

// before
throw new CommandExecutionError(`${commandName}: malformed comment row ${field}`);
// after
if (typeof value === 'number' || typeof value === 'bigint') return String(value);
throw new CommandExecutionError(`${commandName}: malformed comment row ${field}`);
Defensive patterns

Strategy: validation

Validate before calling

if (row.text != null && typeof row.text !== 'string') {
  throw new Error(`Unexpected text type: ${typeof row.text}`);
}

Type guard

function isOptionalString(v) {
  return v == null || typeof v === 'string';
}

Try / catch

try {
  rows = normalizeCommentRows(rawRows, cmd);
} catch (e) {
  if (e instanceof CommandExecutionError && /malformed comment row/.test(e.message)) {
    console.error('Bad row:', JSON.stringify(rawRows).slice(0, 500));
    rows = [];
  } else throw e;
}

Prevention

When it happens

Trigger: row.text (or another field passed in) is a number, object, or array instead of a string, typically because the underlying page data structure changed.

Common situations: XHS comment payload format drift, a proxy/transform layer returning parsed objects instead of strings, or a caller passing raw JSON rows without validation.

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.

Related errors


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