jackwener/OpenCLI · error · CommandExecutionError
eastmoney convertible returned malformed ${field} for ${bond
Error message
eastmoney convertible returned malformed ${field} for ${bondCode || 'unknown bond'} What it means
normalizeEastmoneyNumeric() validates quote metrics from the convertible-bond API. It accepts finite numbers and the literal '-' (Eastmoney's marker for temporarily unavailable data), and throws CommandExecutionError for anything else — meaning a field the code expects to be numeric came back as a string, null, undefined, NaN, or an object.
Source
Thrown at clis/eastmoney/convertible.js:33
value: { fid: 'f236', order: 'desc' }, // 转股价值
// #2109: f239 is the putback trigger price (= convPrice × 0.7), not YTM.
// Renamed so `--sort` no longer claims to order by a value it doesn't hold.
'put-trigger': { fid: 'f239', order: 'desc' }, // 回售触发价
};
const NUMERIC_FIELDS = [
'f2', 'f3', 'f229', 'f230', 'f235', 'f236', 'f237', 'f238', 'f239',
];
function isEastmoneyScalar(value) {
return typeof value === 'string' || typeof value === 'number';
}
function normalizeEastmoneyNumeric(value, field, bondCode) {
if (typeof value === 'number' && Number.isFinite(value)) return value;
// Eastmoney uses "-" for temporarily unavailable quote metrics.
if (value === '-') return value;
throw new CommandExecutionError(`eastmoney convertible returned malformed ${field} for ${bondCode || 'unknown bond'}`);
}
function normalizeEastmoneyString(value, field, bondCode) {
if (isEastmoneyScalar(value)) return String(value);
throw new CommandExecutionError(`eastmoney convertible returned malformed ${field} for ${bondCode || 'unknown bond'}`);
}
function normalizeEastmoneyIdentityString(value, field, bondCode) {
if (typeof value === 'string' && value.trim()) return value;
throw new CommandExecutionError(`eastmoney convertible returned malformed ${field} for ${bondCode || 'unknown bond'}`);
}
export function parseConvertibleLimit(value) {
if (value === undefined || value === null || value === '') return 20;
if (typeof value === 'number') {
if (Number.isInteger(value) && value >= 1 && value <= 100) return value;
throw new ArgumentError('eastmoney convertible --limit must be an integer between 1 and 100');
}View on GitHub (pinned to 49907e53dc)
Solutions
- Inspect the raw API row for the offending field and confirm its current type.
- If Eastmoney now sends numeric strings, preprocess with Number(value) before mapping, or relax the check.
- Treat the throw as data-quality signal: catch CommandExecutionError, log the bond code + field, and skip that row.
- Pin/verify against the current Eastmoney convertible API response format.
Example fix
// before const price = normalizeEastmoneyNumeric(row.PRICE, 'price', code); // after const rawPrice = row.PRICE === '-' ? row.PRICE : (row.PRICE == null ? row.PRICE : Number(row.PRICE)); const price = normalizeEastmoneyNumeric(rawPrice, 'price', code);
Defensive patterns
Strategy: type-guard
Validate before calling
const isOkNumeric = (v) => (typeof v === 'number' && Number.isFinite(v)) || v === '-';
if (!isOkNumeric(row.PRICE)) console.warn('price unavailable for', row.SECURITY_CODE); Type guard
const isEastmoneyNumeric = (v) => (typeof v === 'number' && Number.isFinite(v)) || v === '-';
Try / catch
try {
const mapped = mapConvertibleRow(row);
} catch (e) {
if (e instanceof CommandExecutionError && /malformed/.test(e.message)) {
console.warn(`Skipping row with bad numeric field: ${e.message}`);
} else throw e;
} Prevention
- Pre-coerce numeric-looking strings with Number() before mapping
- Map null to '-' when the API uses '-' for unavailable values
- Dump one raw API row to pin down current field types
- Catch per-row errors so one bad field doesn't kill the whole batch
When it happens
Trigger: A row field (e.g. price, premium rate, volume) is null/undefined, a numeric-looking string like '123.45', NaN, or a nested object — anything not a finite number or '-'. Called from mapConvertibleRow for each numeric column.
Common situations: Eastmoney changes field semantics or units and returns strings; suspended bonds return null instead of '-'; a schema drift makes a column an object after a site update.
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
- Ctrip flight API returned an itinerary without an id
- archive snapshots returned malformed CDX payload: snapshot r
- archive snapshots returned malformed CDX payload: snapshot r
- Bilibili user search returned malformed result for ${input}
- Ctrip flight API returned a malformed batchSearch payload
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/8c66da11e71271b0.
Report an issue: GitHub.