jackwener/OpenCLI · error · CommandExecutionError

${label} returned a malformed article id

Error message

${label} returned a malformed article id

What it means

readArticleId in clis/juejin/utils.js:144 coerces a value to a trimmed string and validates it against JUEJIN_ID (/^\d{16,20}$/) because Juejin content IDs are 19-digit numeric strings. If the article_id from the API row is missing, null, or not a 16-20 digit number, this CommandExecutionError is thrown to prevent building broken https://juejin.cn/post/<id> links.

Source

Thrown at clis/juejin/utils.js:144

}

export function readDataArray(payload, label) {
    if (!payload || typeof payload !== 'object' || Array.isArray(payload) || !Object.hasOwn(payload, 'data')) {
        throw new CommandExecutionError(`${label} returned a malformed payload`);
    }
    if (!Array.isArray(payload.data)) {
        throw new CommandExecutionError(`${label} returned a non-array data field`);
    }
    if (payload.data.length === 0) {
        throw new EmptyResultError(label, `${label} returned no articles.`);
    }
    return payload.data;
}

function readArticleId(value, label) {
    const id = String(value ?? '').trim();
    if (!JUEJIN_ID.test(id)) {
        throw new CommandExecutionError(`${label} returned a malformed article id`);
    }
    return id;
}

function readOptionalNumber(value, label) {
    if (value == null) return null;
    const n = Number(value);
    if (!Number.isFinite(n)) {
        throw new CommandExecutionError(`${label} returned a malformed numeric field`);
    }
    return n;
}

/** Map a recommend-feed row (`item_info.article_info` / `author_user_info`) to a flat shape. */
export function mapFeedItem(row, rank) {
    const info = row?.item_info ?? {};
    const article = info.article_info ?? {};
    const author = info.author_user_info ?? {};

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Dump the offending row (item_info / content object) to see where the id actually lives after an API change.
  2. Filter out non-article rows before mapping: skip rows without item_info.article_info (feed) or with non-numeric content_id (hot).
  3. Update mapFeedItem/mapHotItem field paths if Juejin renamed or moved the id field.
  4. Wrap per-row mapping in try/catch and skip (or log) rows that fail id validation instead of failing the whole command.

Example fix

// before: one bad row aborts the whole listing
const items = rows.map((row, i) => mapFeedItem(row, i + 1));
// after: skip rows without a valid article id
const items = rows
    .filter(row => /^\d{16,20}$/.test(String(row?.item_info?.article_info?.article_id ?? '')))
    .map((row, i) => mapFeedItem(row, i + 1));
Defensive patterns

Strategy: validation

Validate before calling

const JUEJIN_ID = /^\d{16,20}$/;
rows = rows.filter(r =>
  JUEJIN_ID.test(String(r?.item_info?.article_info?.article_id ?? r?.content?.content_id ?? '').trim())
);

Type guard

function hasValidArticleId(row) {
  const id = String(row?.item_info?.article_info?.article_id
    ?? row?.content?.content_id ?? '').trim();
  return /^\d{16,20}$/.test(id);
}

Try / catch

try {
  const items = rows.map((row, i) => mapFeedItem(row, i + 1));
} catch (err) {
  if (err instanceof CommandExecutionError && err.message.includes('malformed article id')) {
    console.error('Skipping feed row without a valid article id (ad/special card?).');
    return;
  }
  throw err;
}

Prevention

When it happens

Trigger: A feed or hot-list row where item_info.article_info.article_id (recommend) or content.content_id (hot) is absent, null, non-numeric, or has the wrong digit count — e.g. an empty row, a promoted/non-article item in the feed, or an API shape change moving the id field.

Common situations: Juejin inserting ad or special cards into the recommend feed lacking article_info; the hot-list endpoint returning entries with a different content type whose content_id is not a 19-digit article id; an API contract change relocating article_id.

Understand the failure class

Related errors


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