{"record":{"id":"846a6ae23f2b3a76","repo":"DIYgod/RSSHub","slug":"failed-to-fetch-channel-data-from-castbox","errorCode":null,"errorMessage":"Failed to fetch channel data from Castbox","messagePattern":"Failed to fetch channel data from Castbox","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/castbox/channel.ts","lineNumber":65,"sourceCode":"    description: `Get the channel from the Castbox channel URL. For example, the URL of the channel \"Lemonade Stand\" is \\`https://castbox.fm/channel/Lemonade-Stand-id6776228\\`, where \\`Lemonade-Stand-id6776228\\` is the \\`channel\\` parameter.\n\nYou can use the RSSHub global \\`limit\\` query parameter to specify the maximum number of episodes to fetch from the Castbox API (defaults to 50). For example: \\`/castbox/channel/Lemonade-Stand-id6776228?limit=100\\`.`,\n    maintainers: ['ananyatimalsina'],\n    handler: async (ctx) => {\n        const { channel } = ctx.req.param();\n        const cid = channel.split('-id', 2)[1];\n\n        if (!cid) {\n            throw new Error('Invalid channel format. Missing -id');\n        }\n\n        const channelParams = { cid, r: 1, raw: 1, web: 1 };\n        const { m: cm, n: cn, queryStr: cQuery } = getNonce(channelParams);\n\n        const channelData = await ofetch(`https://everest.castbox.fm/data/channel/v3?${cQuery}&m=${cm}&n=${cn}`);\n\n        if (!channelData?.data) {\n            throw new Error('Failed to fetch channel data from Castbox');\n        }\n\n        const chData = channelData.data;\n        const limit = ctx.req.query('limit') ? Number(ctx.req.query('limit') as string) : 50;\n\n        const epParams = { cid, limit, r: 1, raw: 1, web: 1 };\n        const { m: em, n: en, queryStr: eQuery } = getNonce(epParams);\n\n        const epData = await ofetch(`https://everest.castbox.fm/data/episode_list/v2?${eQuery}&m=${em}&n=${en}`);\n\n        if (!epData?.data?.episode_list) {\n            throw new Error('Failed to fetch episode list from Castbox');\n        }\n\n        const episodes = epData.data.episode_list;\n\n        const items = episodes.map((ep: any) => {\n            let enclosure_type = 'audio/mpeg';","sourceCodeStart":47,"sourceCodeEnd":83,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/castbox/channel.ts#L47-L83","documentation":"Thrown by the Castbox channel route when the upstream call to `https://everest.castbox.fm/data/channel/v3` returns a falsy or empty `.data` field. This is an upstream/API failure guard, not an input validation. The request itself may have succeeded (HTTP 200) but the body shape was unexpected.","triggerScenarios":"Castbox API returns `{}` or an error envelope without a `data` key; the cid extracted from the URL is invalid/expired and Castbox returns an empty channel; rate limiting returns a 200 with an error body; the nonce/signing in `getNonce` is rejected silently.","commonSituations":"Castbox changes its nonce algorithm or API contract, the channel was deleted, network proxy strips the JSON body, or transient CDN error returning HTML parsed as JSON.","solutions":["Retry the request after a short interval — often transient.","Verify the channel id by opening the castbox.fm URL in a browser; a deleted channel yields no data.","If reproducing consistently across channels, the `getNonce` signing logic likely needs updating to match Castbox's current client.","Inspect the raw `everest.castbox.fm/data/channel/v3` response (with the computed query string) to see the actual error body."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"function hasChannelData(r: unknown): r is { data: Record<string, unknown> } {\n    return typeof r === 'object' && r !== null && 'data' in r && !!r.data;\n}","tryCatchPattern":"try {\n    const channelData = await ofetch(url);\n    if (!channelData?.data) {\n    // retry once, then surface a typed error\n    }\n} catch (e) {\n    throw new Error(`Castbox channel API unreachable: ${(e as Error).message}`);\n}","preventionTips":["Verify the cid by opening the castbox.fm channel URL in a browser first.","When the nonce algorithm changes site-wide, all channels fail at once — that is the signal to update `getNonce`.","Log the raw response status and body during debugging; the falsy `.data` is a symptom, not a cause."],"tags":["upstream-api","network","response-shape","external-service"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}