{"record":{"id":"c6f1563fc542ce08","repo":"DIYgod/RSSHub","slug":"unknown-content-type-for-link-link","errorCode":null,"errorMessage":"Unknown content type for link: ${link}","messagePattern":"Unknown content type for link: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/chikubi/utils.ts","lineNumber":36,"sourceCode":"        title: '.article_title',\n        description: ['.article_icatch', '.article_contents'],\n    },\n};\n\nfunction getContentType(link: string): keyof typeof CONTENT_TYPES {\n    const typePatterns = {\n        doujin: ['/cg/', '/comic/', '/voice/'],\n        video: ['/nipple-video/'],\n        article: ['/post-'],\n    };\n\n    for (const [type, patterns] of Object.entries(typePatterns)) {\n        if (patterns.some((pattern) => link.includes(pattern))) {\n            return type as keyof typeof CONTENT_TYPES;\n        }\n    }\n\n    throw new Error(`Unknown content type for link: ${link}`);\n}\n\nexport async function processItems(list): Promise<DataItem[]> {\n    const items = await Promise.all(\n        list.map((item) =>\n            cache.tryGet(item.link, async () => {\n                const detailResponse = await got(item.link);\n                const $ = load(detailResponse.data);\n\n                const contentType = getContentType(item.link);\n                const selectors = CONTENT_TYPES[contentType];\n\n                const title = $(selectors.title).text().trim() || item.title;\n                const description = processDescription(selectors.description.map((selector) => $(selector).prop('outerHTML')).join(''));\n\n                const pubDateStr = $('meta[property=\"article:published_time\"]').attr('content');\n                const pubDate = pubDateStr ? parseDate(pubDateStr) : undefined;\n","sourceCodeStart":18,"sourceCodeEnd":54,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/chikubi/utils.ts#L18-L54","documentation":"Thrown by `getContentType` in chikubi/utils.ts when a post link does not contain any of the recognised path fragments. Recognised patterns: doujin → ['/cg/', '/comic/', '/voice/'], video → ['/nipple-video/'], article → ['/post-']. Any link missing all of these falls through.","triggerScenarios":"chikubi.jp publishes content under a new URL prefix not in the pattern list (e.g. a new '/news/' or '/special/' section), or a list item's href is relative/empty and the rootUrl prefix masks the real path.","commonSituations":"Site restructure adds a content type the route author never saw, or an item link is malformed (e.g. just '#', or a protocol-relative '//cdn.chikubi.jp/...').","solutions":["Inspect the failing link value (it is included in the message) to see the actual path.","If the path is a legitimate new content type, add its prefix to the relevant array in `typePatterns` (or create a new type with matching `CONTENT_TYPES` selectors).","If links are coming through without their prefix, check how `item.link` is built upstream — likely missing `rootUrl` concatenation."],"exampleFix":"// before\nconst typePatterns = {\n    doujin: ['/cg/', '/comic/', '/voice/'],\n    video: ['/nipple-video/'],\n    article: ['/post-'],\n};\n// after — add newly observed prefix\nconst typePatterns = {\n    doujin: ['/cg/', '/comic/', '/voice/'],\n    video: ['/nipple-video/', '/video-post/'],\n    article: ['/post-'],\n};","handlingStrategy":"validation","validationCode":"const PATTERNS = ['/cg/', '/comic/', '/voice/', '/nipple-video/', '/post-'];\nfunction matchesKnownPattern(link: string): boolean {\n    return PATTERNS.some((p) => link.includes(p));\n}\nif (!matchesKnownPattern(link)) {\n    // log link, skip item, or extend PATTERNS\n}","typeGuard":"function isKnownContentType(link: string): boolean {\n    return ['/cg/', '/comic/', '/voice/', '/nipple-video/', '/post-'].some((p) => link.includes(p));\n}","tryCatchPattern":null,"preventionTips":["Log the offending link — it is in the error message — to spot new content prefixes quickly.","When chikubi.jp adds a section, extend `typePatterns` and `CONTENT_TYPES` together.","Defensively skip (rather than throw) for unrecognised links so one new prefix does not kill the whole feed."],"tags":["response-shape","site-restructure","pattern-matching","string-parsing"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}