jackwener/OpenCLI · error · CommandExecutionError

Failed to fetch Xiaoyuzhou transcript content: ${getErrorMes

Error message

Failed to fetch Xiaoyuzhou transcript content: ${getErrorMessage(error)}

What it means

This error is thrown by fetchXiaoyuzhouTranscriptBody (clis/xiaoyuzhou/auth.js:272) when the HTTP GET request for a Xiaoyuzhou episode transcript page fails at the network/transport level — i.e. fetch() itself rejects before a response is received. The library wraps the underlying cause (DNS failure, timeout, TLS error, aborted connection) into a CommandExecutionError with the message 'Failed to fetch Xiaoyuzhou transcript content: <cause>'. It exists so callers get a uniform CLI error instead of a raw fetch exception.

Source

Thrown at clis/xiaoyuzhou/auth.js:272

        data: parsed?.data,
    };
}

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)) {

View on GitHub (pinned to 49907e53dc)

Solutions

  1. Check network connectivity and confirm the transcript URL is reachable (curl -I <url>)
  2. Retry with a stable connection — the 20s AbortSignal.timeout may be too short on slow links; pre-warm DNS or increase the timeout in auth.js:268 if you control the code
  3. If using Node < 17.3, upgrade Node or polyfill AbortSignal.timeout
  4. If a custom fetchImpl was supplied, verify it does not reject for valid requests (e.g. in tests return a Response-like object)
  5. Inspect the wrapped cause in the error message (text after the colon) to identify the specific transport failure

Example fix

// before
const body = await fetchXiaoyuzhouTranscriptBody(url);
// after
try {
  const body = await fetchXiaoyuzhouTranscriptBody(url);
} catch (error) {
  if (String(error.message).includes('Failed to fetch Xiaoyuzhou transcript content')) {
    console.error('Transcript host unreachable or timed out; check network and retry.');
  }
  throw error;
}
Defensive patterns

Strategy: try-catch

Validate before calling

const ok = await fetch(url, { method: 'HEAD' }).then(r => r.ok).catch(() => false);
if (!ok) throw new Error('Transcript host unreachable; fix network before calling.');

Type guard

null

Try / catch

try {
  const body = await fetchXiaoyuzhouTranscriptBody(url);
} catch (error) {
  if (error instanceof CommandExecutionError && error.message.includes('Failed to fetch Xiaoyuzhou transcript content')) {
    // network/timeout failure — retry with backoff or surface connectivity hint
  } else throw error;
}

Prevention

When it happens

Trigger: Calling fetchXiaoyuzhouTranscriptBody(url) (directly or via the transcriptBody command) when: the network is down or DNS for api.xiaoyuzhoufm/xyzfm transcript host fails; the request exceeds the hardcoded AbortSignal.timeout(20_000); the connection is reset/TLS fails; or a custom fetchImpl passed in rejects.

Common situations: Developer runs the transcript command offline or behind a corporate proxy blocking the host; slow network causing the 20s timeout; transcript URL is stale or redirects to a dead CDN edge; running in a Node version without AbortSignal.timeout support causing an immediate throw; passing a mock fetchImpl in tests that throws.

Related errors


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