{"record":{"id":"bfae3f57b14271b9","repo":"DIYgod/RSSHub","slug":"invalid-language-language-allowed-values-are","errorCode":null,"errorMessage":"Invalid language: ${language}. Allowed values are: ${[...validLanguages].join(', ')}","messagePattern":"Invalid language: (.+?)\\. Allowed values are: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"warning","filePath":"lib/routes/bandisoft/history.ts","lineNumber":142,"sourceCode":"        label: '한국어',\n        value: 'kr',\n    },\n];\n\nexport const handler = async (ctx: Context): Promise<Data> => {\n    const { id = 'bandizip', language = 'en' } = ctx.req.param();\n    const limit = Number(ctx.req.query('limit') ?? '500');\n\n    const validIds = new Set<string>(idOptions.map((option) => option.value));\n\n    if (!validIds.has(id)) {\n        throw new Error(`Invalid id: ${id}. Allowed values are: ${[...validIds].join(', ')}`);\n    }\n\n    const validLanguages = new Set<string>(languageOptions.map((option) => option.value));\n\n    if (!validLanguages.has(language)) {\n        throw new Error(`Invalid language: ${language}. Allowed values are: ${[...validLanguages].join(', ')}`);\n    }\n\n    const baseUrl = `https://${language}.bandisoft.com`;\n    const targetUrl: string = new URL(`${id}/history/`, baseUrl).href;\n\n    const response = await ofetch(targetUrl);\n    const $: CheerioAPI = load(response);\n    const lang = $('html').attr('lang') ?? 'en';\n    const author: string | undefined = $('meta[name=\"author\"]').attr('content');\n\n    const items: DataItem[] = $('div.row')\n        .slice(0, limit)\n        .toArray()\n        .map((el) => {\n            const $el: Cheerio<Element> = $(el);\n\n            const version: string | undefined = $el.find('div.cell1').text();\n            const pubDateStr: string | undefined = $el.find('div.cell2').text();","sourceCodeStart":124,"sourceCodeEnd":160,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/bandisoft/history.ts#L124-L160","documentation":"Thrown by the bandisoft history route when the :language path parameter is not one of the values in languageOptions (en, cn, tw, jp, ru, es, fr, de, it, sk, uk, be, da, pl, br, cs, nl, sl, tr, th, gr, uz, ro, kr). The whitelist is built from languageOptions and the error enumerates every accepted code.","triggerScenarios":"Calling the route with a language code outside the supported set, e.g. 'pt' instead of 'br', or a two-letter code Bandisoft does not host a subdomain for.","commonSituations":"User supplies an ISO code Bandisoft doesn't use; case mismatch; doc lists a removed locale.","solutions":["Pick a code from the error message's allowed list (these map 1:1 to {lang}.bandisoft.com subdomains).","When adding a locale, append it to languageOptions so validation, the example, and the subdomain construction stay in sync."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"const VALID_LANGS = new Set(languageOptions.map((o) => o.value));\nif (!VALID_LANGS.has(language)) {\n    throw new InvalidParameterError(`Invalid language: ${language}. Allowed: ${[...VALID_LANGS].join(', ')}`);\n}","typeGuard":"function isBandisoftLanguage(v: string): boolean {\n    return languageOptions.some((o) => o.value === v);\n}","tryCatchPattern":null,"preventionTips":["Derive the route example and validation from the same languageOptions array.","Document that language maps 1:1 to a {lang}.bandisoft.com subdomain."],"tags":["bandisoft","input-validation","route-parameter","i18n","whitelist"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}