jackwener/OpenCLI · error · CommandExecutionError
Xiaoyuzhou transcript download failed with HTTP ${response.s
Error message
Xiaoyuzhou transcript download failed with HTTP ${response.status}${bodyText ? `: ${bodyText}` : ''} What it means
Thrown by fetchXiaoyuzhouTranscriptBody (clis/xiaoyuzhou/auth.js:276) when the transcript endpoint responded with a non-2xx HTTP status. The library reads the response body and appends it to the message so the server's error payload (rate-limit notice, 403 anti-bot page, 404) is visible. Unlike error 4900, the network round-trip succeeded — the server actively rejected the request.
Source
Thrown at clis/xiaoyuzhou/auth.js:276
export async function fetchXiaoyuzhouTranscriptBody(url, fetchImpl = fetch) {
let response;
try {
response = await fetchImpl(url, {
method: 'GET',
headers: {
'User-Agent': XIAOYUZHOU_DEFAULT_USER_AGENT,
Accept: '*/*',
Market: 'AppStore',
},
signal: AbortSignal.timeout(20_000),
});
}
catch (error) {
throw new CommandExecutionError(`Failed to fetch Xiaoyuzhou transcript content: ${getErrorMessage(error)}`);
}
const bodyText = await response.text();
if (!response.ok) {
throw new CommandExecutionError(`Xiaoyuzhou transcript download failed with HTTP ${response.status}${bodyText ? `: ${bodyText}` : ''}`);
}
return bodyText;
}
export function extractTranscriptText(transcriptBody) {
let parsed;
try {
parsed = JSON.parse(transcriptBody);
}
catch {
return { text: '', segmentCount: 0 };
}
let items = [];
if (Array.isArray(parsed)) {
items = parsed;
}
else if (parsed && typeof parsed === 'object') {
for (const key of ['segments', 'data', 'transcript', 'items']) {View on GitHub (pinned to 49907e53dc)
Solutions
- Read the HTTP status and body appended to the message to determine server-side cause
- For 403, update the User-Agent / Market headers in auth.js:263-266 to match the current official app values
- For 429, add backoff/delay between transcript requests and retry later
- For 404, verify the episode ID/URL is correct and that a transcript actually exists for it
- For 5xx, retry after a delay — it is a server-side outage
Example fix
// before
const body = await fetchXiaoyuzhouTranscriptBody(url);
// after
try {
const body = await fetchXiaoyuzhouTranscriptBody(url);
} catch (error) {
const m = /HTTP (\d{3})/.exec(error.message);
if (m && m[1] === '429') {
await new Promise(r => setTimeout(r, 5000));
return fetchXiaoyuzhouTranscriptBody(url);
}
throw error;
} Defensive patterns
Strategy: retry
Validate before calling
const probe = await fetch(url, { method: 'HEAD' });
if (!probe.ok) console.warn(`Endpoint preflight returned HTTP ${probe.status}; expect failure.`); Type guard
null
Try / catch
try {
const body = await fetchXiaoyuzhouTranscriptBody(url);
} catch (error) {
const status = Number(/HTTP (\d{3})/.exec(error.message)?.[1] ?? 0);
if (status === 429 || status >= 500) { /* wait and retry */ }
else if (status === 403) { /* fix headers/User-Agent */ }
else throw error; // 404 etc. is permanent
} Prevention
- Throttle transcript requests to avoid 429 rate limits
- Keep User-Agent/Market headers in auth.js current with the official app
- Validate episode URLs before fetching to avoid 404s
- Monitor the appended response body in the message for server-side hints
When it happens
Trigger: fetchXiaoyuzhouTranscriptBody(url) returns response.ok === false — e.g. HTTP 403 (CDN/WAF blocking the default User-Agent or the AppStore Market header being rejected), 404 (episode transcript no longer exists / wrong URL), 429 (rate limited), or 5xx (server outage).
Common situations: Scraping many transcripts quickly and hitting rate limits; Xiaoyuzhou changing their CDN rules so the hardcoded User-Agent ('Xiaoyuzhou Default User Agent'/AppStore Market) is blocked; passing an episode ID whose transcript was removed, yielding a 404; transient 502/503 during server incidents.
Related errors
- DuckDuckGo suggest returned HTTP ${resp.status}
- ${label} returned HTTP ${outcome.status}
- linux.do request failed: HTTP ${result.status ?? 'unknown'}
- medium tag returned HTTP ${resp.status}
- HTTP ${result.httpStatus} from ${result.where}
AI-assisted analysis of jackwener/OpenCLI@49907e53dc (2026-08-29).
Data as JSON: /api/errors/c888e91e10cac1e7.
Report an issue: GitHub.