{"record":{"id":"f52ae1b615703d06","repo":"DIYgod/RSSHub","slug":"bad-category-see-a-href-https-docs-rsshub-app-f52ae1","errorCode":null,"errorMessage":"Bad category. See <a href=\"https://docs.rsshub.app/routes/new-media#mei-hua-wang-wen-zhang\">docs</a>","messagePattern":"Bad category\\. See <a href=\"https://docs\\.rsshub\\.app/routes/new-media#mei-hua-wang-wen-zhang\">docs</a>","errorType":"exception","errorClass":null,"httpStatus":503,"severity":"warning","filePath":"lib/routes-deprecated/meihua/article.js","lineNumber":18,"sourceCode":"const got = require('@/utils/got');\nconst cheerio = require('cheerio');\n\nconst config = {\n    latest: {\n        link: 'article!2',\n        title: '最新',\n    },\n    hot: {\n        link: 'article!3',\n        title: '热门',\n    },\n};\n\nmodule.exports = async (ctx) => {\n    const cfg = config[ctx.params.caty];\n    if (!cfg) {\n        throw new Error('Bad category. See <a href=\"https://docs.rsshub.app/routes/new-media#mei-hua-wang-wen-zhang\">docs</a>');\n    }\n\n    const currentUrl = `https://www.meihua.info/${cfg.link}`;\n    const response = await got({\n        method: 'get',\n        url: currentUrl,\n    });\n    const data = JSON.parse(response.data.match(/\"compositionStore\":(.*?),\"detailStore\":/)[1]);\n\n    const shotList = data.compositionsData.list.map((item) => ({\n        title: item.title,\n        link: `https://www.meihua.info/article/${item.compositionId}`,\n        pubDate: new Date(item.gmtPublish).toUTCString(),\n    }));\n\n    const items = await Promise.all(\n        shotList.map((item) =>\n            ctx.cache.tryGet(item.link, async () => {","sourceCodeStart":1,"sourceCodeEnd":36,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes-deprecated/meihua/article.js#L1-L36","documentation":"Thrown by the Meihua (梅花网) article route (deprecated) when :caty is not a config key. Config maps slugs (e.g. a 'latest' key → article!2 最新, hot → article!3 热门) to Meihua section tokens used in the URL. Miss throws before the JSON scrape.","triggerScenarios":"Request with a :caty not in config; config[ctx.params.caty] is undefined and the throw fires.","commonSituations":"Slug typo, or Meihua renaming its section tokens (article!2 etc.) so config was pruned. The route then regex-parses compositionStore out of the HTML, so even valid slugs break if the site markup changes.","solutions":["Use a documented slug (e.g. the latest/newest key or hot).","Read the config map at the top of lib/routes-deprecated/meihua/article.js for exact keys.","If the throw passes but JSON.parse fails downstream, the site markup changed — report the route."],"exampleFix":"// before\nGET /meihua/article/hott   // typo\n// after\nGET /meihua/article/hot      // 热门","handlingStrategy":"validation","validationCode":"const VALID = ['hot' /* + latest/newest key — see config in lib/routes-deprecated/meihua/article.js */];\nif (!VALID.includes(ctx.params.caty)) throw new Error(`Invalid caty. Valid: ${VALID.join(', ')}`);","typeGuard":"const isCaty = (v: string): v is 'hot' => v === 'hot';","tryCatchPattern":"try { await fetch(route); }\ncatch (e) {\n  if (/Bad category/.test(e.message)) listSlugs();\n  else if (/JSON.parse/.test(String(e))) reportMarkupChange();\n  else throw e;\n}","preventionTips":["Distinguish article! tokens from shots! tokens.","Markup changes break the regex even with a valid slug."],"tags":["rsshub","parameter-validation","deprecated-route","new-media"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}