jackwener/OpenCLI · error · CommandExecutionError

toutiao recommend returned a non-array data field

Error message

toutiao recommend returned a non-array data field

What it means

This CommandExecutionError is thrown when the toutiao recommend response payload's data field is present but not an array. The library expects payload.data to be an array of recommendation rows and fails fast otherwise to prevent downstream .map() crashes.

Source

Thrown at clis/toutiao/recommend.js:64

                },
            });
        } catch (error) {
            throw new CommandExecutionError(`toutiao recommend request failed: ${error?.message || error}`);
        }
        if (!resp.ok) {
            throw new CommandExecutionError(`toutiao recommend failed: HTTP ${resp.status}`);
        }
        let payload;
        try {
            payload = await resp.json();
        } catch (error) {
            throw new CommandExecutionError(`toutiao recommend returned malformed JSON: ${error?.message || error}`);
        }
        if (payload?.message && payload.message !== 'success') {
            throw new CommandExecutionError(`toutiao recommend returned message=${payload.message}`);
        }
        if (!Array.isArray(payload?.data)) {
            throw new CommandExecutionError('toutiao recommend returned a non-array data field');
        }
        const rows = payload.data.map(mapRecommendRow).filter(Boolean).slice(0, limit);
        if (rows.length === 0) {
            throw new EmptyResultError('toutiao recommend', `频道 ${category} 返回空列表。`);
        }
        // Re-rank (1..N) after filter so ranks are dense even if upstream had ads.
        return rows.map((row, idx) => ({ ...row, rank: idx + 1 }));
    },
});

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Log the full payload once to see the actual shape of payload.data.
  2. If upstream changed the shape, update recommend.js to read the new field (e.g. payload.data.list).
  3. Upgrade the library if a newer version already handles the changed upstream schema.
  4. Treat as upstream incident and retry later if the shape is normally an array.

Example fix

// before
const rows = await recommend({ category: 'tech' });
// after
try {
  var rows = await recommend({ category: 'tech' });
} catch (e) {
  if (String(e.message).includes('non-array data field')) {
    console.error('Upstream schema changed or error body returned');
    return [];
  }
  throw e;
}
Defensive patterns

Strategy: type-guard

Type guard

function isRecommendPayload(p) {
  return p != null && typeof p === 'object' &&
    (p.message === undefined || p.message === 'success') &&
    Array.isArray(p.data);
}

Try / catch

try {
  return await recommend({ category });
} catch (e) {
  if (String(e.message).includes('non-array data field')) {
    console.error('Upstream schema changed; inspect raw payload');
    return [];
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling 'toutiao recommend' when the upstream returns 200 JSON whose payload.data is null, an object, a string, or missing entirely — e.g. an error-shaped body that skipped the message check, or a schema change.

Common situations: Upstream contract change (data became an object keyed by category); upstream returning an error body with a different shape that still parses as JSON; partial/malformed responses during upstream incidents.

Related errors


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