{"record":{"id":"a79f0dab10b2a223","repo":"DIYgod/RSSHub","slug":"unknown-type-item-type-a79f0d","errorCode":null,"errorMessage":"Unknown type: ${item.type}","messagePattern":"Unknown type: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/economist/global-business-review.ts","lineNumber":35,"sourceCode":"const DESCRIPTION = {\n    en: 'The Economist Global Business Review is a new bilingual digital app from the editors of The Economist Group.',\n    cn: '《经济学人·商论》是《经济学人》2015年5月推出的旗下中英双语APP，萃取《经济学人》在商业、金融、科技等领域的精华文章，为中国读者呈现全球视角的深度分析，并鼓励中国的读者批判性地思考中国和全球重大议题。',\n    tw: '《經濟學人·商論》是經濟學人集團官方中英雙語電子APP，萃取《經濟學人》在商業、金融、科技等領域的精華文章，為中國讀者呈現全球視角的深度分析，並鼓勵中國的讀者批判性地思考中國和全球的重大議題。',\n};\n\nconst parseContent = function (item, article_id, language) {\n    switch (item.type) {\n        case 'paragraph':\n            return parseParagraph(item.data, language);\n\n        case 'image':\n            return parseImage(item.data, article_id, language);\n\n        case 'subtitle':\n            return parseParagraph(item.data, language, 'h3');\n\n        default:\n            throw new Error(`Unknown type: ${item.type}`);\n    }\n};\n\nconst parseTitle = function (data, language) {\n    const content = Object.assign({}, ...data.map((x) => ({ [x.lang]: x.text })));\n    return language.map((item) => content[ALLOW_LANGUAGE[item]]).join('');\n};\n\nconst parseParagraph = function (data, language, type = 'p') {\n    const content = Object.assign({}, ...data.map((x) => ({ [x.lang]: x.text })));\n    return `<div>${language.map((item) => `<${type}>${content[ALLOW_LANGUAGE[item]]}</${type}>`).join('')}</div>`;\n};\n\nconst parseImage = function (data, article_id, language) {\n    const content = Object.assign({}, ...data.map((x) => ({ [x.lang]: x.image_path })));\n    return `<div><img src=\"https://businessreviewglobal-cdn.com/article_images/${article_id}/${encodeURIComponent(content[ALLOW_LANGUAGE[language[0]]])}\"/></div>`;\n};\n","sourceCodeStart":17,"sourceCodeEnd":53,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/economist/global-business-review.ts#L17-L53","documentation":"Thrown by the `parseContent` function in the Economist Global Business Review route when iterating over article body items from the Hummingbird API. The switch handles `paragraph`, `image`, and `subtitle` types. Any other `item.type` hits the default case and throws. This is a forward-compatibility guard: it surfaces schema changes from the upstream API rather than silently dropping content.","triggerScenarios":"The Economist/Hummingbird API adds a new content block type to the article body array (e.g., `video`, `quote`, `pull-quote`, `divider`, `tweet`). The route iterates `data.content.map((item) => parseContent(item, ...))` and the unhandled type reaches the default case.","commonSituations":"The Economist redesigns the Global Business Review app and introduces new content blocks. An article contains an embedded interactive element with a type the parser has never seen. The API version changes and old types are renamed.","solutions":["Log the unknown `item.type` value to identify what new block the API introduced.","Add a new case branch for the type if it carries meaningful content, or return an empty string to skip it gracefully.","If the type is cosmetic (divider, spacer), return `''` instead of throwing so the rest of the article renders.","Check the API response structure at `https://api.hummingbird.businessreview.global/api/article/index?id=<id>` for the full schema."],"exampleFix":"// before\ndefault:\n    throw new Error(`Unknown type: ${item.type}`);\n\n// after — skip unknown types gracefully instead of failing the entire article\n// Add a console.warn for visibility during development\ndefault:\n    console.warn(`Unknown Economist content type: ${item.type}`);\n    return '';","handlingStrategy":"type-guard","validationCode":"const KNOWN_CONTENT_TYPES = new Set(['paragraph', 'image', 'subtitle']);\n\nfunction hasKnownType(item: { type: string }): boolean {\n    return KNOWN_CONTENT_TYPES.has(item.type);\n}","typeGuard":"type KnownContentType = 'paragraph' | 'image' | 'subtitle';\n\nfunction isKnownContentType(item: { type: string }): item is { type: KnownContentType; data: any } {\n    return item.type === 'paragraph' || item.type === 'image' || item.type === 'subtitle';\n}","tryCatchPattern":"// Filter out unknown content types before mapping, or handle them gracefully\nconst html = data.content\n    .filter(isKnownContentType)\n    .map((item) => parseContent(item, article_id, language))\n    .join('');","preventionTips":["Design content parsers to gracefully skip unknown types rather than throwing.","Log unknown types to a monitoring channel so schema changes are detected early.","Periodically check the upstream API schema for new content block types.","Use a filter-then-map pattern to isolate parsing failures from unknown types."],"tags":["schema-evolution","upstream-api","content-parsing","economist"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}