{"record":{"id":"ce987e515a233f5c","repo":"jackwener/OpenCLI","slug":"failed-to-fetch-xiaoyuzhou-transcript-content-g","errorCode":null,"errorMessage":"Failed to fetch Xiaoyuzhou transcript content: ${getErrorMessage(error)}","messagePattern":"Failed to fetch Xiaoyuzhou transcript content: (.+?)","errorType":"exception","errorClass":"CommandExecutionError","httpStatus":null,"severity":"error","filePath":"clis/xiaoyuzhou/auth.js","lineNumber":272,"sourceCode":"        data: parsed?.data,\n    };\n}\n\nexport async function fetchXiaoyuzhouTranscriptBody(url, fetchImpl = fetch) {\n    let response;\n    try {\n        response = await fetchImpl(url, {\n            method: 'GET',\n            headers: {\n                'User-Agent': XIAOYUZHOU_DEFAULT_USER_AGENT,\n                Accept: '*/*',\n                Market: 'AppStore',\n            },\n            signal: AbortSignal.timeout(20_000),\n        });\n    }\n    catch (error) {\n        throw new CommandExecutionError(`Failed to fetch Xiaoyuzhou transcript content: ${getErrorMessage(error)}`);\n    }\n    const bodyText = await response.text();\n    if (!response.ok) {\n        throw new CommandExecutionError(`Xiaoyuzhou transcript download failed with HTTP ${response.status}${bodyText ? `: ${bodyText}` : ''}`);\n    }\n    return bodyText;\n}\n\nexport function extractTranscriptText(transcriptBody) {\n    let parsed;\n    try {\n        parsed = JSON.parse(transcriptBody);\n    }\n    catch {\n        return { text: '', segmentCount: 0 };\n    }\n    let items = [];\n    if (Array.isArray(parsed)) {","sourceCodeStart":254,"sourceCodeEnd":290,"githubUrl":"https://github.com/jackwener/OpenCLI/blob/49907e53dc3ade5c223ff0c4c2c2785687cec4e6/clis/xiaoyuzhou/auth.js#L254-L290","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check network connectivity and confirm the transcript URL is reachable (curl -I <url>)","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","If using Node < 17.3, upgrade Node or polyfill AbortSignal.timeout","If a custom fetchImpl was supplied, verify it does not reject for valid requests (e.g. in tests return a Response-like object)","Inspect the wrapped cause in the error message (text after the colon) to identify the specific transport failure"],"exampleFix":"// before\nconst body = await fetchXiaoyuzhouTranscriptBody(url);\n// after\ntry {\n  const body = await fetchXiaoyuzhouTranscriptBody(url);\n} catch (error) {\n  if (String(error.message).includes('Failed to fetch Xiaoyuzhou transcript content')) {\n    console.error('Transcript host unreachable or timed out; check network and retry.');\n  }\n  throw error;\n}","handlingStrategy":"try-catch","validationCode":"const ok = await fetch(url, { method: 'HEAD' }).then(r => r.ok).catch(() => false);\nif (!ok) throw new Error('Transcript host unreachable; fix network before calling.');","typeGuard":"null","tryCatchPattern":"try {\n  const body = await fetchXiaoyuzhouTranscriptBody(url);\n} catch (error) {\n  if (error instanceof CommandExecutionError && error.message.includes('Failed to fetch Xiaoyuzhou transcript content')) {\n    // network/timeout failure — retry with backoff or surface connectivity hint\n  } else throw error;\n}","preventionTips":["Check connectivity/DNS to the transcript host before batch jobs","Raise the 20s timeout for slow links if you control the code","Avoid custom fetchImpl that rejects on valid requests","Run batch transcript jobs with retry + exponential backoff"],"tags":["network","fetch","timeout","cli"],"backgroundTag":"network-request-failed","analyzedSha":"49907e53dc3ade5c223ff0c4c2c2785687cec4e6","analyzedAt":"2026-08-29T08:14:47.543Z","schemaVersion":2},"datasetVersion":"2026-08-29T12:17:43.993Z"}