{"record":{"id":"4450f4d8e02eb0c3","repo":"DIYgod/RSSHub","slug":"tag-not-found-4450f4","errorCode":null,"errorMessage":"Tag not found","messagePattern":"Tag not found","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":503,"severity":"warning","filePath":"lib/routes/baai/hub.ts","lineNumber":61,"sourceCode":"    maintainers: ['TonyRL'],\n    handler,\n};\n\nasync function handler(ctx) {\n    const { tagId = '', sort = 'new', range } = ctx.req.param();\n\n    let title, description, brief, iconUrl;\n    if (tagId) {\n        const tagsData = await getTagsData();\n\n        const tag = (tagsData as Array<Record<string, string>>).find((tag) => tag.id === tagId);\n        if (tag) {\n            title = tag.title;\n            description = tag.description;\n            brief = tag.brief;\n            iconUrl = tag.iconUrl;\n        } else {\n            throw new InvalidParameterError('Tag not found');\n        }\n    }\n\n    const response = await ofetch(`${apiHost}/api/v1/story/list`, {\n        method: 'POST',\n        query: {\n            page: 1,\n            sort,\n            tag_id: tagId,\n            time_range: range,\n        },\n    });\n\n    const list = response.data.map((item) => parseItem(item));\n\n    const items = await Promise.all(\n        list.map((item) =>\n            cache.tryGet(item.link, async () => {","sourceCodeStart":43,"sourceCodeEnd":79,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/baai/hub.ts#L43-L79","documentation":"Thrown by the baai hub route when a tagId is supplied but does not match any entry returned by getTagsData(). It uses InvalidParameterError so RSSHub surfaces a clear 400-style message instead of fetching an empty story list.","triggerScenarios":"Calling the route with a tagId path parameter whose value is not present in the tags dataset returned by getTagsData(); the find() returns undefined and the else branch throws.","commonSituations":"Stale tagId from old documentation; BAAI renames or removes a tag; user copies a numeric id that was never a tag.","solutions":["Look up the current tag list via getTagsData (or the route's documented options) and use a valid tag id.","If you want all stories, omit tagId so the validation block is skipped entirely."],"exampleFix":"// before\nconst tag = (tagsData as Array<Record<string, string>>).find((tag) => tag.id === tagId);\nif (tag) { /* ... */ } else {\n    throw new InvalidParameterError('Tag not found');\n}\n\n// after: list valid ids in the error so the caller can self-correct\nconst tag = tagsData.find((t) => t.id === tagId);\nif (!tag) {\n    const valid = tagsData.map((t) => t.id).join(', ');\n    throw new InvalidParameterError(`Tag not found: ${tagId}. Valid ids: ${valid}`);\n}","handlingStrategy":"validation","validationCode":"const tagsData = await getTagsData();\nconst tag = tagsData.find((t) => t.id === tagId);\nif (!tag) {\n    throw new InvalidParameterError(`Tag not found: ${tagId}. Valid: ${tagsData.map((t) => t.id).join(', ')}`);\n}","typeGuard":"function isKnownTagId(tagsData: Array<{ id: string }>, id: string): boolean {\n    return tagsData.some((t) => t.id === id);\n}","tryCatchPattern":null,"preventionTips":["Cache getTagsData() results to avoid re-fetching on every validation.","Include the list of valid ids in the error so callers can self-correct."],"tags":["baai","input-validation","lookup","route-parameter"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}