jackwener/OpenCLI · error · CommandExecutionError

${commandName}: malformed comment row image URL

Error message

${commandName}: malformed comment row image URL

What it means

Each entry in a comment row's images array must be a string URL. A non-string element (number, object, null item) throws this CommandExecutionError because the URL cannot be parsed safely.

Source

Thrown at clis/xiaohongshu/comments.js:85

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 {
            parsed = new URL(trimmed);
        }
        catch {
            throw new CommandExecutionError(`${commandName}: malformed comment row image URL`);
        }
        if ((parsed.protocol !== 'https:' && parsed.protocol !== 'http:') || parsed.username || parsed.password) {
            throw new CommandExecutionError(`${commandName}: malformed comment row image URL`);
        }
        const href = parsed.toString();
        if (!urls.includes(href))
            urls.push(href);
    }
    return urls;
}

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Inspect the array element that is not a string and map it to its url property before normalizing.
  2. Add a pre-parse step converting image objects to their URL strings.
  3. Update normalizeCommentImages to accept {url}-style objects.
  4. Validate each element with typeof === 'string' before calling the API.

Example fix

// before
normalizeCommentImages(row.images, cmd);
// after
const imgs = (row.images ?? []).map(i => typeof i === 'string' ? i : i?.url);
normalizeCommentImages(imgs, cmd);
Defensive patterns

Strategy: type-guard

Validate before calling

const bad = (row.images ?? []).filter(i => typeof i !== 'string');
if (bad.length) throw new Error(`${bad.length} non-string image entries`);

Type guard

function isStringArray(v) {
  return Array.isArray(v) && v.every(x => typeof x === 'string');
}

Try / catch

try {
  urls = normalizeCommentImages(row.images, cmd);
} catch (e) {
  if (e instanceof CommandExecutionError && /image URL/.test(e.message)) {
    urls = [];
  } else throw e;
}

Prevention

When it happens

Trigger: The images array contains a non-string element, e.g. an image descriptor object { url, width } instead of the plain URL string.

Common situations: XHS payload drift to structured image objects, or caller mapping rows incorrectly and pushing objects into the images 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.

Related errors


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