jackwener/OpenCLI · error · CommandExecutionError
${label} returned a malformed numeric field
Error message
${label} returned a malformed numeric field What it means
readOptionalNumber validates optional numeric fields coming from Juejin API rows (feed items, hot items). If a field is present (not null/undefined) but Number() yields NaN/Infinity — e.g. a string like 'abc' or an object — it throws CommandExecutionError because the API returned data that does not fit the expected numeric schema. This guards downstream mapping code from silently producing NaN values.
Source
Thrown at clis/juejin/utils.js:153
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 ?? {};
const tags = Array.isArray(info.tags)
? info.tags.map(t => t?.tag_name).filter(Boolean).slice(0, 6).join(', ')
: '';
const articleId = readArticleId(article.article_id, 'juejin recommend');
return {
rank,
article_id: articleId,
title: String(article.title ?? '').trim(),
brief: String(article.brief_content ?? '').trim(),View on GitHub (pinned to 49907e53dc)
Solutions
- Check the raw API row (curl https://api.juejin.cn/... or log `value`) to see the actual field value
- Re-run the command — the malformed value is often transient garbage from one row
- Update the adapter's mapFeedItem/mapHotItem if Juejin changed the field format, adding normalization (e.g. parse '1.2w')
- If a specific field is chronically non-numeric, pass null/omit it instead of feeding it to readOptionalNumber
Example fix
// before
readOptionalNumber(row.item_info.article_info.view_count, 'view_count') // value = '1.2万' -> throws
// after
function parseCNNumber(v) {
if (v == null) return null;
if (typeof v === 'string') {
const m = v.match(/^([\d.]+)([万w]?)$/i);
if (m) return Number(m[1]) * (m[2] ? 10000 : 1);
}
return readOptionalNumber(v, 'view_count');
} Defensive patterns
Strategy: validation
Validate before calling
function safeNumber(v) {
if (v == null) return null;
const n = Number(v);
return Number.isFinite(n) ? n : null;
}
const views = safeNumber(row?.item_info?.article_info?.view_count);
if (views === null && row?.item_info?.article_info?.view_count != null) {
console.warn('skipping malformed row', row.item_info.article_id);
} Type guard
function isNumericField(v) {
return v == null || (typeof v === 'number' && Number.isFinite(v)) ||
(typeof v === 'string' && v.trim() !== '' && Number.isFinite(Number(v)));
} Try / catch
try {
const item = mapFeedItem(row, rank);
} catch (e) {
if (/malformed numeric field/.test(e.message)) {
console.warn(`skip row ${row?.item_info?.article_id}: ${e.message}`);
return null;
}
throw e;
} Prevention
- Pre-validate each API row with a small normalizer before mapping
- Log raw payloads when Juejin changes its API schema
- Skip-and-log malformed rows instead of failing the whole feed
- Pin/alert on Juejin API shape changes via a smoke test
When it happens
Trigger: mapFeedItem or mapHotItem passes an `article_info`/`author_user_info` field (e.g. view_count, digg_count) that is a non-numeric string or object instead of a number or numeric string; Juejin changed its API response shape; the field is a placeholder like '-' or ''.
Common situations: Juejin ships an API schema change (field becomes a formatted string like '1.2w'); a partially-degraded/edge response row has nulls coerced oddly; scraping a preview/test endpoint with mock data.
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
- ${label} returned err_no ${payload.err_no}: ${payload.err_ms
- ${label} returned a malformed payload
- ${label} returned a non-array data field
- Sina Finance rolling news API returned malformed row ${index
- Zhihu answer comments contained a ${role} row without a stab
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/7546fe6020cf0733.
Report an issue: GitHub.