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

  1. Use one of the documented slugs: clashroyale, brawlstars, clashofclans, boombeach, hayday (lowercase, no separators).
  2. 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

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


AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12). Data as JSON: /api/errors/4328ba1df28a272e. Report an issue: GitHub.