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
- Log the offending comment row to inspect the actual field type.
- Update the normalizer to coerce or handle the new shape (e.g. text as { content: ... } object).
- Pre-validate scraped rows with a schema check before calling the comments API.
- 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
- Log raw scraped rows so shape drift is visible in failures.
- Coerce numeric-like text fields to strings before normalizing.
- Pin library versions and test against live XHS after frontend deploys.
- Validate rows with a lightweight schema before calling normalize.
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.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- ${commandName}: malformed comment row images
- ${commandName}: malformed comments payload
- ${commandName}: malformed comment row at index ${index}
- Unexpected Xiaohongshu search harvest row ${index + 1} shape
- Unexpected Xiaohongshu search harvest row ${index + 1} shape
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/ba569f9e44aa2ea4.
Report an issue: GitHub.