{"record":{"id":"44f973a84994f88e","repo":"DIYgod/RSSHub","slug":"unknown-post-type-type","errorCode":null,"errorMessage":"Unknown post type: ${type}","messagePattern":"Unknown post type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"lib/routes/otobanana/utils.tsx","lineNumber":70,"sourceCode":"    comments: live.comment_count,\n});\n\nconst renderPost = ({ id, type_label: type, cast, /** livestream  */ message /** , event */ }) => {\n    switch (type) {\n        case 'cast':\n            return renderCast(cast);\n        case 'message':\n            return {\n                title: message.text.split('\\n', 1)[0],\n                description: message.text.replaceAll('\\n', '<br>'),\n                pubDate: parseDate(message.created_at),\n                link: `https://otobanana.com/${type}/${id}`,\n                author: `${message.user.name} (@${message.user.username})`,\n                upvotes: message.like_count,\n                comments: message.comment_count,\n            };\n        default:\n            throw new Error(`Unknown post type: ${type}`);\n    }\n};\n\nexport { apiBase, baseUrl, getUserInfo, renderCast, renderLive, renderPost };\n","sourceCodeStart":52,"sourceCodeEnd":75,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/otobanana/utils.tsx#L52-L75","documentation":"A default-branch throw in renderPost's switch, fired when an otobanana post's type_label is neither 'cast' nor 'message'. Each known type has a dedicated renderer; anything else means the API returned a post shape the renderer was never taught to handle.","triggerScenarios":"The otobanana API returns a post whose type_label is a new/unexpected value (e.g. 'live', 'event', 'poll'). renderPost destructures type_label from the post and switches on it; the default branch throws, surfacing the unhandled type verbatim.","commonSituations":"Otobanana shipped a new post type (livestream, event) after the route was written; a post object has type_label undefined because a field was renamed upstream, so the switch falls through to default.","solutions":["Inspect the failing post object (log the full payload) to learn the new type_label value.","Add a renderer case for the new type (reuse renderLive from utils.tsx for 'live', etc.).","If some posts should be skipped rather than fatal, return a filtered-out sentinel and drop it instead of throwing.","Keep the switch exhaustive by deriving the union of supported types from a shared constant."],"exampleFix":"// before\ndefault:\n    throw new Error(`Unknown post type: ${type}`);\n\n// after — skip unsupported types instead of failing the whole feed\nconst KNOWN_TYPES = new Set(['cast', 'message', 'live']);\n// in caller:\nconst items = posts.map(renderPost).filter((item) => item !== null);\n// in renderPost default:\ndefault:\n    return null; // caller filters nulls","handlingStrategy":"type-guard","validationCode":"const SUPPORTED_POST_TYPES = new Set(['cast', 'message']);\nfunction shouldRender(type: string): boolean {\n    return SUPPORTED_POST_TYPES.has(type);\n}\nconst renderable = posts.filter((p) => shouldRender(p.type_label));","typeGuard":"type SupportedPostType = 'cast' | 'message';\nconst isSupportedPostType = (t: string): t is SupportedPostType => t === 'cast' || t === 'message';","tryCatchPattern":"// Make renderPost total: unknown types yield null and the caller drops them.\nfunction tryRenderPost(post: any) {\n    try {\n        return renderPost(post);\n    } catch (e) {\n        if (e instanceof Error && /Unknown post type/.test(e.message)) return null;\n        throw e;\n    }\n}\nconst items = posts.map(tryRenderPost).filter((x): x is NonNullable<typeof x> => x !== null);","preventionTips":["Derive the supported-type set from a single constant shared by renderPost and the caller's filter.","Log unsupported types so new post types are noticed without breaking the feed.","Consider skipping over a single bad post instead of failing the whole feed."],"tags":["api","upstream-change","switch-exhaustiveness","data-validation"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}