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

  1. Compare the live response (curl the full URL with fs=b:MK0354 and current ut token) against the expected `{data:{diff:[...]}}` shape.
  2. Ensure query params (np=1, fltt=2, invt=2, fid, fields) are sent unchanged — removing any can change the shape.
  3. Fix test fixtures to include a non-empty `diff` array.
  4. If eastmoney renamed `diff`, update extractConvertibleDiff accordingly.
  5. 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

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

Related errors


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