jackwener/OpenCLI · error · CommandExecutionError

toutiao recommend returned message=${payload.message}

Error message

toutiao recommend returned message=${payload.message}

What it means

This CommandExecutionError is thrown when the toutiao recommend payload contains a message field whose value is not 'success'. The upstream API signals business-level failures inside a 200 JSON body via this message field, and the library surfaces it verbatim.

Source

Thrown at clis/toutiao/recommend.js:61

                    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36',
                    Accept: 'application/json',
                    Referer: 'https://www.toutiao.com/',
                },
            });
        } 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. Read the embedded message value to learn what upstream rejected (it is printed verbatim in the error).
  2. Slow down request rate and add cookies/headers if the message indicates risk control or frequency limits.
  3. If upstream legitimately changed its success marker, update the `payload.message !== 'success'` check in recommend.js to match the new contract.
  4. Retry later if the message indicates a temporary upstream condition.
Defensive patterns

Strategy: try-catch

Try / catch

try {
  return await recommend({ category });
} catch (e) {
  const m = /returned message=(.+)/.exec(e.message);
  if (m) {
    console.error('Upstream business error:', m[1]);
    return []; // degrade gracefully
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling 'toutiao recommend' when the parsed JSON has payload.message set to anything other than 'success' — e.g. risk-control rejections, quota/permission errors, or other upstream business errors.

Common situations: Toutiao risk-control flagging the request as automated; API contract change introducing a new message value the check does not recognize; regional restrictions reported via message instead of HTTP status.

Related errors


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