DIYgod/RSSHub · error · Error
Unsupported game: ${game}. Supported games: ${Object.keys(GA
Error message
Unsupported game: ${game}. Supported games: ${Object.keys(GAME_NAMES).join(', ')} What it means
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.
Source
Thrown at lib/routes/supercell/blog.ts:195
if (item.image?.url) {
parts.push(`<img src="${item.image.url}" alt="${item.image.title || ''}">`);
}
}
}
break;
default:
break;
}
return parts.join('');
}
async function handler(ctx: any) {
const game: string = ctx.req.param('game');
const locale: string = ctx.req.param('locale') || '';
if (!Object.hasOwn(GAME_NAMES, game)) {
throw new Error(`Unsupported game: ${game}. Supported games: ${Object.keys(GAME_NAMES).join(', ')}`);
}
const localePrefix = locale ? `/${locale}` : '';
const rootUrl = 'https://supercell.com';
const currentUrl = `${rootUrl}/en/games/${game}${localePrefix}/blog/`;
const { data: response } = await got(currentUrl);
// 用正则提取 __NEXT_DATA__ JSON
const match = response.match(/<script id="__NEXT_DATA__" type="application\/json">(.+?)<\/script>/);
const nextData = match ? JSON.parse(match[1]) : {};
const articles = nextData.props.pageProps.articles || [];
const buildId = nextData.buildId;
const items = await Promise.all(
articles.map((article) => {
const link = `${rootUrl}${article.linkUrl}`;
const pubDate = parseDate(article.publishDate);
View on GitHub (pinned to bed535e087)
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).
Example fix
// before GET /supercell/squadbusters/blog // after GET /supercell/clashroyale/blog
Defensive patterns
Strategy: type-guard
Validate before calling
const SUPPORTED_GAMES = ['clashroyale', 'brawlstars', 'clashofclans', 'boombeach', 'hayday'] as const;
function isSupportedGame(game: string): boolean {
return (SUPPORTED_GAMES as readonly string[]).includes(game);
}
// usage
if (!isSupportedGame(game)) {
// reject early with the documented list
} Type guard
const GAME_NAMES = {
clashroyale: 'Clash Royale',
brawlstars: 'Brawl Stars',
clashofclans: 'Clash of Clans',
boombeach: 'Boom Beach',
hayday: 'Hay Day',
} as const;
type SupportedGame = keyof typeof GAME_NAMES;
function isSupportedGame(game: string): game is SupportedGame {
return Object.hasOwn(GAME_NAMES, game);
} Prevention
- 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.
When it happens
Trigger: /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'.
Common situations: 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.
Related errors
- Invalid type: ${category}
- Invalid type: ${type}
- Invalid type: ${type}
- Invalid k: k=${k}
- Invalid type: ${type}
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/4328ba1df28a272e.
Report an issue: GitHub.