{"record":{"id":"48fb1f0432285697","repo":"DIYgod/RSSHub","slug":"invalid-response","errorCode":null,"errorMessage":"Invalid response","messagePattern":"Invalid response","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/douyu/room.ts","lineNumber":37,"sourceCode":"            source: ['www.douyu.com/:id', 'www.douyu.com/'],\n        },\n    ],\n    name: '直播间开播',\n    maintainers: ['DIYgod', 'ChaosTong'],\n    handler,\n};\n\nasync function handler(ctx) {\n    const id = ctx.req.param('id');\n\n    let data;\n    let item;\n    let room_thumb;\n    try {\n        const response = await ofetch(`https://www.douyu.com/betard/${id}`);\n\n        if (!response.room) {\n            throw new Error('Invalid response');\n        }\n\n        data = response.room;\n        room_thumb = data.room_pic;\n\n        if (data.show_status === 1) {\n            item = [\n                {\n                    title: `${data.videoLoop === 1 ? '视频轮播' : '开播'}: ${data.room_name}`,\n                    pubDate: new Date(data.show_time * 1000).toUTCString(),\n                    guid: data.show_time,\n                    link: `https://www.douyu.com/${id}`,\n                    description: `<img src=\"${room_thumb}\">`,\n                },\n            ];\n        }\n        // make a fallback to the old api\n    } catch {","sourceCodeStart":19,"sourceCodeEnd":55,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/douyu/room.ts#L19-L55","documentation":"Thrown by the Douyu live room route when the `/betard/<id>` API response does not contain a `room` property. The betard API returns the room metadata as JSON; if the room doesn't exist or the API format changed, the `room` field is absent. This is a plain Error thrown inside a try-catch block that also catches network errors.","triggerScenarios":"The room ID doesn't exist (no streamer with that ID); the betard API returned an error object without a room field; the API endpoint structure changed; the room ID contains special characters that weren't properly handled.","commonSituations":"User enters an incorrect or expired room ID; Douyu restructured the betard API; the room was permanently closed by Douyu.","solutions":["Verify the room ID by visiting https://www.douyu.com/<id> in a browser.","Find the correct ID from the streamer's Douyu page URL.","If the API structure changed, check for RSSHub updates."],"exampleFix":"// before\nif (!response.room) {\n    throw new Error('Invalid response');\n}\n\n// after\nif (!response.room) {\n    throw new Error(`Invalid response from Douyu betard API for room ${id}. The room may not exist or the API format has changed.`);\n}","handlingStrategy":"validation","validationCode":"// Pre-validate the Douyu room ID\nfunction isValidDouyuRoomId(id: string): boolean {\n    return /^\\d+$/.test(id) || /^[a-zA-Z0-9]+$/.test(id);\n}\n\n// Pre-flight check: verify the room exists\nasync function checkDouyuRoom(id: string): Promise<boolean> {\n    try {\n        const resp = await fetch(`https://www.douyu.com/betard/${id}`);\n        const data = await resp.json();\n        return !!data.room;\n    } catch {\n        return false;\n    }\n}","typeGuard":"interface DouyuBetardResponse {\n    room?: {\n        room_name: string;\n        show_status: number;\n        room_pic: string;\n    };\n}\n\nfunction isValidDouyuResponse(data: unknown): data is DouyuBetardResponse {\n    return typeof data === 'object' && data !== null && typeof (data as any).room === 'object';\n}","tryCatchPattern":"try {\n    const feed = await fetch(`${rsshubUrl}/douyu/room/${id}`);\n} catch (e) {\n    if (e.message.includes('Invalid response')) {\n        console.error(`Room ${id} may not exist or the Douyu API changed.`);\n    }\n    throw e;\n}","preventionTips":["Verify the room ID by visiting https://www.douyu.com/<id> in a browser.","Note that some Douyu rooms use alphabetic IDs, not just numeric.","Check for RSSHub updates if the betard API structure changes."],"tags":["douyu","api-error","invalid-response","live-streaming"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}