{"record":{"id":"d2864f820d396dc8","repo":"DIYgod/RSSHub","slug":"no-topic-named-topic","errorCode":null,"errorMessage":"No topic named ${topic}","messagePattern":"No topic named (.+?)","errorType":"validation","errorClass":"InvalidParameterError","httpStatus":null,"severity":"error","filePath":"lib/routes/utgd/topic.ts","lineNumber":48,"sourceCode":"    description: `| 在线阅读专栏 | 卡片笔记专题 |\n| ------------ | ------------ |\n\n更多专栏请见 [专题广场](https://utgd.net/topic)`,\n};\n\nasync function handler(ctx) {\n    const topic = ctx.req.param('topic') ?? '在线阅读专栏';\n    const limit = ctx.req.query('limit') ? Number.parseInt(ctx.req.query('limit')) : 20;\n\n    const currentUrl = `${rootUrl}/topic`;\n    const topicUrl = `${apiRootUrl}/api/v2/topic/`;\n\n    let response = await ofetch(topicUrl);\n\n    const topicItem = response.find((i) => i.title === topic);\n\n    if (!topicItem) {\n        throw new InvalidParameterError(`No topic named ${topic}`);\n    }\n\n    const apiUrl = `${rootUrl}/api/v2/topic/${topicItem.id}/article/`;\n\n    response = await ofetch(apiUrl);\n\n    const list = parseResult(response.results, limit);\n\n    const items = await Promise.all(list.map((item) => parseArticle(item)));\n\n    return {\n        title: `UNTAG - ${topicItem.title}`,\n        link: currentUrl,\n        item: items,\n        description: topicItem.summary,\n    };\n}\n","sourceCodeStart":30,"sourceCodeEnd":66,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/utgd/topic.ts#L30-L66","documentation":"Thrown by the UTAG (utgd.net) topic route when the `topic` path parameter does not match any `title` in the `/api/v2/topic/` listing response. The route fetches the full topic list from the API and searches for an exact title match. This is an `InvalidParameterError` (HTTP 400). The default topic is `在线阅读专栏`.","triggerScenarios":"A request to `/utgd/topic/:topic` where `:topic` is a string that does not exactly match (case-sensitive, full-string) any topic title returned by `https://utgd.net/api/v2/topic/`. For example, a topic name that was renamed, deleted, or that contains trailing whitespace.","commonSituations":"The topic was renamed or removed from the platform since the user's subscription URL was created; the user passed a partial or approximate topic name; or whitespace/encoding differences between the URL and the API title.","solutions":["Browse https://utgd.net/topic to find the exact current topic title and use it verbatim in the URL.","Omit the topic parameter to use the default `在线阅读专栏`.","URL-encode the topic name if it contains special characters."],"exampleFix":"// before\nGET /utgd/topic/old-topic-name\n// after\nGET /utgd/topic/在线阅读专栏","handlingStrategy":"validation","validationCode":"// Before calling the handler, verify the topic exists\n// (This requires an API call, so it's done inside the handler itself)\nconst response = await ofetch(topicUrl);\nconst topicItem = response.find((i) => i.title === topic);\nif (!topicItem) {\n    throw new InvalidParameterError(\n        `No topic named '${topic}'. Available topics: ${response.map((i) => i.title).join(', ')}`\n    );\n}","typeGuard":null,"tryCatchPattern":"try {\n    const feed = await fetch('/utgd/topic/' + encodeURIComponent(topic));\n} catch (e) {\n    if (e.name === 'InvalidParameterError') {\n        // topic doesn't exist; fall back to default or prompt user\n    }\n}","preventionTips":["URL-encode the topic name to preserve special characters.","Use the exact title from https://utgd.net/topic as displayed.","Include available topic names in the error message to aid debugging."],"tags":["parameter-validation","invalid-parameter","api-lookup","utgd","rss-route"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}