{"record":{"id":"4328ba1df28a272e","repo":"DIYgod/RSSHub","slug":"unsupported-game-game-supported-games-obje","errorCode":null,"errorMessage":"Unsupported game: ${game}. Supported games: ${Object.keys(GAME_NAMES).join(', ')}","messagePattern":"Unsupported game: (.+?)\\. Supported games: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/supercell/blog.ts","lineNumber":195,"sourceCode":"                    if (item.image?.url) {\n                        parts.push(`<img src=\"${item.image.url}\" alt=\"${item.image.title || ''}\">`);\n                    }\n                }\n            }\n            break;\n        default:\n            break;\n    }\n\n    return parts.join('');\n}\n\nasync function handler(ctx: any) {\n    const game: string = ctx.req.param('game');\n    const locale: string = ctx.req.param('locale') || '';\n\n    if (!Object.hasOwn(GAME_NAMES, game)) {\n        throw new Error(`Unsupported game: ${game}. Supported games: ${Object.keys(GAME_NAMES).join(', ')}`);\n    }\n\n    const localePrefix = locale ? `/${locale}` : '';\n    const rootUrl = 'https://supercell.com';\n    const currentUrl = `${rootUrl}/en/games/${game}${localePrefix}/blog/`;\n\n    const { data: response } = await got(currentUrl);\n    // 用正则提取 __NEXT_DATA__ JSON\n    const match = response.match(/<script id=\"__NEXT_DATA__\" type=\"application\\/json\">(.+?)<\\/script>/);\n    const nextData = match ? JSON.parse(match[1]) : {};\n    const articles = nextData.props.pageProps.articles || [];\n    const buildId = nextData.buildId;\n\n    const items = await Promise.all(\n        articles.map((article) => {\n            const link = `${rootUrl}${article.linkUrl}`;\n            const pubDate = parseDate(article.publishDate);\n","sourceCodeStart":177,"sourceCodeEnd":213,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/supercell/blog.ts#L177-L213","documentation":"Thrown by supercell/blog.ts:198 via `throw new Error(...)` (note: NOT an InvalidParameterError — inconsistent with RSSHub conventions, so it will not be mapped to a clean HTTP 400) when Object.hasOwn(GAME_NAMES, game) is false. GAME_NAMES (line 59) has exactly five keys: clashroyale, brawlstars, clashofclans, boombeach, hayday. The check runs at the very top of the handler, before any network request, so it fails fast.","triggerScenarios":"/supercell/<game>/blog[/<locale>] with a game slug outside the five supported: e.g. 'squadbusters', 'moco', a display name like 'Clash Royale', or a typo such as 'clash-royale'.","commonSituations":"Supercell ships a new title (e.g. Squad Busters) that the route has not been updated to support; the user guesses a slug; the user uses the human-readable game name instead of the slug.","solutions":["Use one of the documented slugs: clashroyale, brawlstars, clashofclans, boombeach, hayday (lowercase, no separators).","If you need a newer Supercell title, open an issue or PR adding it to the GAME_NAMES map (and ideally convert the throw to InvalidParameterError while there)."],"exampleFix":"// before\nGET /supercell/squadbusters/blog\n// after\nGET /supercell/clashroyale/blog","handlingStrategy":"type-guard","validationCode":"const SUPPORTED_GAMES = ['clashroyale', 'brawlstars', 'clashofclans', 'boombeach', 'hayday'] as const;\n\nfunction isSupportedGame(game: string): boolean {\n  return (SUPPORTED_GAMES as readonly string[]).includes(game);\n}\n\n// usage\nif (!isSupportedGame(game)) {\n  // reject early with the documented list\n}","typeGuard":"const GAME_NAMES = {\n  clashroyale: 'Clash Royale',\n  brawlstars: 'Brawl Stars',\n  clashofclans: 'Clash of Clans',\n  boombeach: 'Boom Beach',\n  hayday: 'Hay Day',\n} as const;\n\ntype SupportedGame = keyof typeof GAME_NAMES;\n\nfunction isSupportedGame(game: string): game is SupportedGame {\n  return Object.hasOwn(GAME_NAMES, game);\n}","tryCatchPattern":null,"preventionTips":["Always use lowercase slugs from the GAME_NAMES table; never the display name.","When Supercell releases a new game, add it to GAME_NAMES before users request it.","Consider converting this throw to InvalidParameterError for a clean 400 response."],"tags":["invalid-parameter","user-input","enum","supercell","wrong-error-type"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}