{"record":{"id":"02002f8b68e37c17","repo":"DIYgod/RSSHub","slug":"userorerror-typename","errorCode":null,"errorMessage":"${userOrError.__typename}","messagePattern":"\\$\\{userOrError\\.__typename\\}","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/twitch/live.ts","lineNumber":102,"sourceCode":"                extensions: {\n                    persistedQuery: {\n                        version: 1,\n                        sha256Hash: '0df42c4d26990ec1216d0b815c92cc4a4a806e25b352b66ac1dd91d5a1d59b80',\n                    },\n                },\n            },\n        ],\n    });\n\n    const channelShellData = response.data[0].data;\n    const streamMetadataData = response.data[1].data;\n    const realtimeStreamTagListData = response.data[2].data;\n    const channelRootAboutPanelData = response.data[3].data;\n    const { userOrError } = channelShellData;\n    const { user } = channelRootAboutPanelData;\n\n    if (!userOrError.id) {\n        throw new Error(userOrError.__typename);\n    }\n\n    const displayName = userOrError.displayName;\n\n    const liveItem: DataItem[] = [];\n\n    if (streamMetadataData.user.stream) {\n        liveItem.push({\n            title: streamMetadataData.user.lastBroadcast.title,\n            author: displayName,\n            category: realtimeStreamTagListData.user.stream.freeformTags.map((item) => item.name),\n            description: `<img style=\"max-width: 100%;\" src=\"https://static-cdn.jtvnw.net/previews-ttv/live_user_${login}.jpg\">`,\n            pubDate: parseDate(streamMetadataData.user.stream.createdAt),\n            guid: streamMetadataData.user.stream.id,\n            link: `https://www.twitch.tv/${login}`,\n        });\n    }\n","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/twitch/live.ts#L84-L120","documentation":"Generic Error from the Twitch live route: when the GraphQL `channelShellData.userOrError` has no `id`, the handler throws `userOrError.__typename` directly. That typename is Twitch's error discriminant (commonly `UserDoesntExist` or `InvalidUser`), so the thrown message is whatever Twitch returned.","triggerScenarios":"A request to `/twitch/live/:login` where the login does not resolve to a Twitch user; Twitch's GQL response sets `userOrError.__typename` to an error type and omits `id`, triggering line 101-102.","commonSituations":"Typo in the login; the channel was renamed/deactivated; the persisted-query hash on the GQL call is stale and Twitch returns a different error shape.","solutions":["Verify the login exists by opening https://www.twitch.tv/{login}.","If the channel renamed, use the new login.","If logins are valid but the error persists, confirm the GQL persistedQuery sha256Hash is still current (Twitch rotates these)."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"if (!userOrError?.id) { throw new InvalidParameterError(`Twitch login not found: ${userOrError?.__typename ?? 'unknown'}`); }","typeGuard":"const isTwitchUser = (u: unknown): u is { id: string; displayName: string } => typeof u === 'object' && u !== null && typeof (u as any).id === 'string';","tryCatchPattern":"try { /* live handler */ }\ncatch (e) { if (e instanceof Error && /(UserDoesntExist|InvalidUser)/.test(e.message)) { /* surface 404 for the login */ } else throw e; }","preventionTips":["Validate the login format before the GQL call","Track Twitch's persisted-query hash drift","Map known __typename errors to stable HTTP statuses"],"tags":["twitch","graphql","invalid-parameter","user-not-found","gql"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}