jackwener/OpenCLI · error · CommandExecutionError

Sina Finance rolling news API returned malformed data

Error message

Sina Finance rolling news API returned malformed data

What it means

CommandExecutionError thrown by normalizeRollRows when payload.result.data is not an array. The library guards against Sina changing the response shape (or an error page being parsed) so map() doesn't crash on undefined. It indicates the response passed the status check but the data field is missing or of the wrong type.

Source

Thrown at clis/sinafinance/rolling-news.js:32

    return String(value).padStart(2, '0');
}

function formatRollTimestamp(value) {
    const seconds = Number(value);
    if (!Number.isFinite(seconds) || seconds <= 0)
        return '';
    // Sina's roll page presents finance news in China Standard Time.
    const date = new Date(seconds * 1000 + 8 * 60 * 60 * 1000);
    return `${pad2(date.getUTCMonth() + 1)}-${pad2(date.getUTCDate())} ${pad2(date.getUTCHours())}:${pad2(date.getUTCMinutes())}`;
}

function normalizeRollRows(payload) {
    if (payload?.result?.status?.code !== 0) {
        throw new CommandExecutionError(`Sina Finance rolling news API failed: ${payload?.result?.status?.msg || 'unknown status'}`);
    }
    const items = payload?.result?.data;
    if (!Array.isArray(items)) {
        throw new CommandExecutionError('Sina Finance rolling news API returned malformed data');
    }
    if (items.length === 0) {
        throw new EmptyResultError('sinafinance rolling-news');
    }
    return items.map((item, index) => {
        const title = typeof item?.title === 'string' ? item.title.trim() : '';
        const url = typeof item?.url === 'string' ? item.url.trim() : '';
        const date = formatRollTimestamp(item?.ctime);
        if (!title || !url || !date) {
            throw new CommandExecutionError(`Sina Finance rolling news API returned malformed row ${index + 1}`);
        }
        return {
            column: '财经',
            title,
            date,
            url,
        };
    });

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the full raw payload to inspect the actual response shape
  2. Check if Sina changed the API response structure and update the CLI
  3. Bypass proxies/VPN to rule out payload rewriting
  4. Pin/report the issue so the parser is updated to the new schema

Example fix

// before
const items = payload?.result?.data; // now an object {list: [...]}
// after
const items = payload?.result?.data?.list ?? payload?.result?.data;
Defensive patterns

Strategy: type-guard

Type guard

function hasRollDataArray(payload) {
  return Array.isArray(payload?.result?.data);
}

Try / catch

try {
  const rows = await cli.rollingNews();
} catch (err) {
  if (/returned malformed data/.test(err.message)) {
    // response shape changed; dump raw payload for diagnosis
    console.error('Sina rolling news schema changed? Inspect raw payload');
  }
  throw err;
}

Prevention

When it happens

Trigger: The rolling news API returns status.code === 0 but result.data is undefined, an object, or null — typically after a Sina API schema change, or an intermediary (proxy/captive portal) injecting content.

Common situations: Sina silently upgrading their API and relocating the data array; a corporate proxy returning a rewritten payload with status code 0; caching layers returning stale/different schemas.

Understand the failure class

Related errors


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