{"record":{"id":"788cbdbba6e10387","repo":"DIYgod/RSSHub","slug":"invalid-tagid","errorCode":null,"errorMessage":"Invalid tagId","messagePattern":"Invalid tagId","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/foodtalks/tag.ts","lineNumber":32,"sourceCode":"    radar: [\n        {\n            source: ['www.foodtalks.cn/news/tag/:tagId'],\n        },\n    ],\n    name: '标签',\n    maintainers: ['TonyRL'],\n    handler,\n    url: 'www.foodtalks.cn',\n};\n\nconst getTagName = async (tagId: string) => {\n    const response = await ofetch(`${apiBaseUrl}/basic/tag/${tagId}?language=ZH`, {\n        headers: {\n            referer: `${baseUrl}/`,\n        },\n    });\n    if (!response.data) {\n        throw new Error('Invalid tagId');\n    }\n    return response.data.name;\n};\n\nasync function handler(ctx) {\n    const { tagId } = ctx.req.param();\n    const limit = Number(ctx.req.query('limit')) || 15;\n\n    const response = await ofetch(`${apiBaseUrl}/news/news/page`, {\n        headers: {\n            referer: `${baseUrl}/`,\n        },\n        query: {\n            current: 1,\n            size: limit,\n            tagId,\n            language: 'ZH',\n        },","sourceCodeStart":14,"sourceCodeEnd":50,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/foodtalks/tag.ts#L14-L50","documentation":"The FoodTalks API endpoint /basic/tag/{tagId} is expected to return a response object whose data field contains the tag metadata. When data is falsy (null or undefined), the tag does not exist in the system, so the route throws 'Invalid tagId' before attempting to fetch articles. This is a precondition check that fails fast rather than emitting an empty or broken feed.","triggerScenarios":"Calling the route with a tagId that is not registered in FoodTalks, a tagId copied from an old URL that was since deleted, or a tagId with trailing characters/whitespace that does not match any record. The API returns a 200 with an empty/null data payload rather than a 404.","commonSituations":"Users pasting a tag slug or name instead of the numeric tagId; tags being retired on the FoodTalks site; locale mismatches (the request hardcodes language=ZH) for tags that only exist in the EN locale.","solutions":["Confirm the tagId by opening the FoodTalks website and copying the numeric ID from the tag page URL or the API response.","URL-encode or trim the tagId to remove accidental whitespace or path separators before the lookup.","If the tag may be locale-specific, verify it exists for language=ZH (the hardcoded query) or extend the route to accept a language parameter.","Fall back to the source website's tag page directly to confirm the tag is still active."],"exampleFix":"// before\nconst response = await ofetch(`${apiBaseUrl}/basic/tag/${tagId}?language=ZH`, { headers: { referer: `${baseUrl}/` } });\nif (!response.data) {\n    throw new Error('Invalid tagId');\n}\n\n// after\nconst trimmedId = tagId.trim();\nconst response = await ofetch(`${apiBaseUrl}/basic/tag/${encodeURIComponent(trimmedId)}?language=ZH`, { headers: { referer: `${baseUrl}/` } });\nif (!response.data) {\n    throw new InvalidParameterError(`Tag \"${trimmedId}\" does not exist on FoodTalks`);\n}","handlingStrategy":"validation","validationCode":"const trimmed = tagId.trim();\nif (!trimmed) throw new InvalidParameterError('tagId is required');","typeGuard":"const isNonEmptyId = (v: string | undefined): v is string => !!v && v.trim().length > 0;","tryCatchPattern":null,"preventionTips":["Trim and URL-encode tagId before the API call.","Document where to find the numeric tag ID on the FoodTalks site.","Consider accepting a language parameter instead of hardcoding ZH."],"tags":["api","validation","user-input"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}