{"record":{"id":"5fd5f265afa4e12c","repo":"DIYgod/RSSHub","slug":"unsupported-element-type-element-type","errorCode":null,"errorMessage":"Unsupported element type: ${element.type}","messagePattern":"Unsupported element type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/rfa/index.ts","lineNumber":63,"sourceCode":"            const stream = element.streams?.find((s) => s.stream_type === 'mp4');\n            return stream ? `<figure><video controls src=\"${stream.url}\" poster=\"${element.promo_image?.url ?? ''}\"></video>${element.headlines?.basic ? `<figcaption>${element.headlines.basic}</figcaption>` : ''}</figure>` : '';\n        }\n        case 'oembed_response':\n            return element.raw_oembed?.html ?? '';\n        case 'list': {\n            const tag = element.list_type === 'ordered' ? 'ol' : 'ul';\n            return `<${tag}>${element.items.map((el) => `<li>${el.content}</li>`).join('')}</${tag}>`;\n        }\n        case 'gallery':\n            return element.content_elements.map((el) => renderElement(el)).join('');\n        case 'quote':\n            return `<blockquote>${element.content_elements.map((el) => renderElement(el)).join('')}${element.citation?.content ? `<cite>${element.citation.content}</cite>` : ''}</blockquote>`;\n        case 'raw_html':\n            return element.content;\n        case 'custom_embed':\n            return '';\n        default:\n            throw new Error(`Unsupported element type: ${element.type}`);\n    }\n};\n\nasync function handler(ctx: Context) {\n    const { language = 'english', channel, subChannel } = ctx.req.param();\n    const baseUrl = 'https://www.rfa.org';\n    const link = `${baseUrl}/${[language, channel, subChannel].filter(Boolean).join('/')}/`;\n\n    const response = await ofetch(link);\n    const $ = load(response);\n    const contentCache = JSON.parse(response.match(/Fusion\\.contentCache=(\\{.*?\\});Fusion\\.layout/)?.[1] ?? '{}');\n\n    const list = new Map<string, any>(\n        Object.values<any>(contentCache['content-api-collections'] ?? {})\n            .flatMap((entry) => entry.data?.content_elements ?? [])\n            .map((story) => [story._id, story])\n    )\n        .values()","sourceCodeStart":45,"sourceCodeEnd":81,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/rfa/index.ts#L45-L81","documentation":"The RFA (Radio Free Asia) route renders structured `content_elements` from a JSON Fusion cache embedded in the page. `renderElement` is a switch over known element types (text, list, gallery, quote, raw_html, custom_embed). The `default` branch throws a generic `Error` with the unrecognized `element.type` whenever the upstream introduces a new element kind the renderer does not know about. This is a defensive exhaustiveness guard, not user input.","triggerScenarios":"The RFA CMS ships a new content_element type (e.g. `video`, `audio`, `table`, `tweet`) not covered by the switch. Any article containing that element triggers the throw on feed generation. The error is data-driven, not parameter-driven.","commonSituations":"Site redesign or CMS upgrade on rfa.org adds a previously-unseen block type; an article embeds a social post or live stream that the renderer never had to handle before.","solutions":["Inspect the value of `element.type` from the error message, then add a `case` to `renderElement` in lib/routes/rfa/index.ts that maps it to the appropriate HTML (often `<div>${renderChildren}</div>` or a passthrough of `element.content`).","If the new type is rare or has no useful representation, add a `case` that returns `''` (like `custom_embed`) instead of falling through to the throw.","Re-fetch the failing article after the patch to confirm the feed builds."],"exampleFix":"// before\ncase 'raw_html':\n    return element.content;\ncase 'custom_embed':\n    return '';\ndefault:\n    throw new Error(`Unsupported element type: ${element.type}`);\n\n// after\ncase 'raw_html':\n    return element.content;\ncase 'custom_embed':\n    return '';\ncase 'video':\n    return `<video src=\"${element.url}\" controls></video>`;\ndefault:\n    return '';","handlingStrategy":"type-guard","validationCode":"const KNOWN_TYPES = new Set(['text', 'header', 'list', 'gallery', 'quote', 'raw_html', 'custom_embed']);\nif (!KNOWN_TYPES.has(element.type)) {\n    // log and return empty string instead of throwing\n    return '';\n}","typeGuard":"const isKnownElementType = (t: unknown): boolean =>\n    typeof t === 'string' && KNOWN_TYPES.has(t);","tryCatchPattern":"try {\n    html = renderElement(el);\n} catch (e) {\n    if (e instanceof Error && e.message.startsWith('Unsupported element type')) {\n        html = '';\n    } else throw e;\n}","preventionTips":["Add new cases to renderElement proactively whenever the upstream CMS ships a new block type.","Log the unknown type so you learn about schema drift before users do.","Replace the `default` throw with a soft fallback for production resilience."],"tags":["content-rendering","exhaustiveness","upstream-change"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}