jackwener/OpenCLI · error · CommandExecutionError
eastmoney convertible returned malformed diff data
Error message
eastmoney convertible returned malformed diff data
What it means
Thrown by extractConvertibleDiff (clis/eastmoney/convertible.js:68) when `data.data` exists but `data.data.diff` is not an array. The push2 clist contract guarantees `diff` is the array of quote rows; if it is absent or another type, the CLI cannot proceed. This is a CommandExecutionError signalling the nested response shape does not match the documented eastmoney clist format.
Source
Thrown at clis/eastmoney/convertible.js:68
throw new ArgumentError('eastmoney convertible --limit must be an integer between 1 and 100');
}
const raw = String(value).trim();
if (!/^\d+$/.test(raw)) throw new ArgumentError('eastmoney convertible --limit must be an integer between 1 and 100');
const parsed = Number(raw);
if (parsed < 1 || parsed > 100) throw new ArgumentError('eastmoney convertible --limit must be an integer between 1 and 100');
return parsed;
}
export function extractConvertibleDiff(data) {
if (!data || typeof data !== 'object' || Array.isArray(data)) {
throw new CommandExecutionError('eastmoney convertible returned a malformed response envelope');
}
if (!data.data || typeof data.data !== 'object' || Array.isArray(data.data)) {
throw new CommandExecutionError('eastmoney convertible returned a malformed data envelope');
}
const diff = data.data.diff;
if (!Array.isArray(diff)) {
throw new CommandExecutionError('eastmoney convertible returned malformed diff data');
}
if (diff.length === 0) {
throw new EmptyResultError('eastmoney convertible');
}
return diff;
}
// Map a raw eastmoney clist `diff` item to an output row.
//
// #2109: f238 / f239 were previously emitted as `remainingYears` / `ytm`, but
// cross-verification (12/12 fingerprint hits) shows f239 is the putback trigger
// price (= convPrice × 0.7) and f238 is the pure-bond premium %. Real YTM /
// remaining term are not in this response's `fields`; adding the correct f-codes
// is a follow-up that needs a live push2 field dump cross-checked against jisilu.
export function mapConvertibleRow(it, rank) {
if (!it || typeof it !== 'object' || Array.isArray(it)) {
throw new CommandExecutionError(`eastmoney convertible returned malformed row at rank ${rank}`);
}View on GitHub (pinned to 49907e53dc)
Solutions
- Compare the live response (curl the full URL with fs=b:MK0354 and current ut token) against the expected `{data:{diff:[...]}}` shape.
- Ensure query params (np=1, fltt=2, invt=2, fid, fields) are sent unchanged — removing any can change the shape.
- Fix test fixtures to include a non-empty `diff` array.
- If eastmoney renamed `diff`, update extractConvertibleDiff accordingly.
- Validate `Array.isArray(json?.data?.diff)` in caller code before mapping.
Example fix
// before
const diff = extractConvertibleDiff(json);
// after
const raw = json?.data?.diff;
if (!Array.isArray(raw)) {
throw new Error('expected data.diff array, got: ' + typeof raw);
}
const diff = extractConvertibleDiff(json); Defensive patterns
Strategy: type-guard
Validate before calling
if (!Array.isArray(json?.data?.diff)) {
throw new Error('expected data.data.diff to be an array');
} Type guard
function hasDiffArray(v) {
return Array.isArray(v?.data?.diff);
} Try / catch
try {
const diff = extractConvertibleDiff(json);
} catch (e) {
if (String(e.message).includes('malformed diff data')) {
console.error('eastmoney clist shape changed — inspect raw payload');
return null;
}
throw e;
} Prevention
- Send all query params (np=1, fltt=2, invt=2) — omitting them changes the response shape.
- Snapshot real responses in fixtures so shape drift is caught in CI.
- Never hand-edit fixtures without the diff key.
- Diff the live response against the expected schema after eastmoney API announcements.
When it happens
Trigger: The API returns `{ data: { ... } }` without `diff` (e.g. np/fltt params rejected, field-set change), or returns `diff` as an object/null; also occurs when stale mocks or an intercepting layer reshapes the payload before extractConvertibleDiff runs.
Common situations: Eastmoney silently changing clist response fields or query-param behavior; passing hand-written test fixtures missing the `diff` key; middleware/JSON transforms mangling the payload; calling with unsupported sort fid causing a different response structure.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- eastmoney convertible returned a malformed response envelope
- eastmoney convertible returned a malformed data envelope
- ${label} returned a malformed payload
- Chess.com stats payload for ${kind} is not an object
- Chess.com stats payload for ${kind}.last is not an object
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/0fac13375b024c4a.
Report an issue: GitHub.