jackwener/OpenCLI · error · CliError
PARSE_ERROR
PARSE_ERROR
Error message
PARSE_ERROR
What it means
After calling POST /v1/episode/list, the CLI expects `response.data` to be an array of episodes. If the API returns an object, null, or a wrapped envelope instead, a CliError with code PARSE_ERROR is thrown so the user knows the response shape changed rather than silently emitting garbage rows.
Source
Thrown at clis/xiaoyuzhou/podcast-episodes.js:31
args: [
{ name: 'id', positional: true, required: true, help: 'Podcast ID (from xiaoyuzhoufm.com URL)' },
{ name: 'limit', type: 'int', default: 20, help: 'Max episodes to show' },
],
columns: ['eid', 'title', 'duration', 'plays', 'date'],
func: async (args) => {
const requestedLimit = Number(args.limit);
if (!Number.isInteger(requestedLimit) || requestedLimit < 1) {
throw new CliError('INVALID_ARGUMENT', 'limit must be a positive integer', 'Example: --limit 5');
}
const credentials = loadXiaoyuzhouCredentials();
const response = await requestXiaoyuzhouJson('/v1/episode/list', {
method: 'POST',
body: { pid: args.id, order: 'desc', limit: requestedLimit },
credentials,
});
const episodes = response.data ?? [];
if (!Array.isArray(episodes)) {
throw new CliError('PARSE_ERROR', 'Unexpected API response format', 'Expected an array of episodes');
}
return episodes.map((ep) => ({
eid: ep.eid,
title: ep.title,
duration: formatDuration(ep.duration),
plays: ep.playCount,
date: formatDate(ep.pubDate),
}));
},
});
View on GitHub (pinned to 49907e53dc)
Solutions
- Re-run the command; transient error envelopes can cause this
- Verify credentials are valid (`xq`-style auth failures can change the payload shape)
- Check for xiaoyuzhou API/CLI version mismatch and update the CLI
- Inspect the raw response (e.g. via verbose logging) to confirm the new schema
Defensive patterns
Strategy: type-guard
Validate before calling
const res = await requestXiaoyuzhouJson('/v1/episode/list', {method:'POST', body:{pid, order:'desc', limit}});
if (!Array.isArray(res?.data)) throw new Error('Unexpected episode list shape'); Type guard
const isEpisodeArray = (d) => Array.isArray(d) && d.every(e => e && typeof e.eid === 'string');
Try / catch
try { const eps = await fetchEpisodes(pid, limit); } catch (e) { if (String(e).includes('PARSE_ERROR')) { logRawResponseForDebugging(); } throw e; } Prevention
- Assert response.data is an array before mapping
- Pin and monitor the CLI/API versions together
- Log raw payloads on failure to detect schema drift early
- Handle wrapped envelopes like {items: []} defensively
When it happens
Trigger: The xiaoyuzhou API returns a non-array `data` field for /v1/episode/list — e.g. an error envelope `{error: ...}`, `{data: {items: []}}` shape change, or an HTML/JSON error page parsed into an object.
Common situations: API version drift after a xiaoyuzhou backend update, hitting a rate-limit or auth-failure payload that isn't the expected list, or a proxy/captive portal returning HTML that gets parsed as a JSON object.
Related errors
- coingecko top
- coingecko trending failed: HTTP ${resp.status}
- coingecko returned no trending coins.
- ${label} returned malformed items payload
- returned malformed items payload
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/49d3d093e8bd0e3b.
Report an issue: GitHub.