{"record":{"id":"bc1685d010f82ab7","repo":"DIYgod/RSSHub","slug":"unknown-placeholder-type-placeholder-type-in","errorCode":null,"errorMessage":"Unknown placeholder type: ${placeholder?.type} in ${link}","messagePattern":"Unknown placeholder type: (.+?) in (.+?)","errorType":"exception","errorClass":"Error","httpStatus":503,"severity":"error","filePath":"lib/routes/afr/utils.ts","lineNumber":76,"sourceCode":"\n            case 'linkExternal':\n                $el.replaceWith(`<a href=\"${placeholder.data.url}\" target=\"_blank\" rel=\"noopener\">${placeholder.data.text}</a>`);\n                break;\n\n            case 'quote':\n                $el.replaceWith(placeholder.data.markup);\n                break;\n\n            case 'scribd':\n                $el.replaceWith(`<a href=\"${placeholder.data.url}\" target=\"_blank\" rel=\"noopener\">View on Scribd</a>`);\n                break;\n\n            case 'twitter':\n                $el.replaceWith(`<a href=\"${placeholder.data.url}\">${placeholder.data.url}</a>`);\n                break;\n\n            default:\n                throw new Error(`Unknown placeholder type: ${placeholder?.type} in ${link}`);\n        }\n    });\n\n    return $.html();\n};\n","sourceCodeStart":58,"sourceCodeEnd":82,"githubUrl":"https://github.com/DIYgod/RSSHub/blob/bed535e0879dc71c5aff6f1e7bd1ac21ede40115/lib/routes/afr/utils.ts#L58-L82","documentation":"AFR article HTML embeds <x-placeholder> elements that renderArticle replaces for known types (markup, scribd, twitter, …). An unknown placeholder type triggers a generic `Error` with the placeholder type and the article link.","triggerScenarios":"AFR adds a new embed/placeholder type to article HTML (e.g. a new social platform, an iframe widget) that the switch does not yet cover.","commonSituations":"Upstream adds a new embeddable block; an article uses a feature not previously seen in the feed.","solutions":["Report the placeholder.type and link to maintainers so a new case can be added.","As a maintainer, add a new case to the switch and emit a sensible replacement (link or markup).","Short-term, default to replacing unknown placeholders with empty string rather than throwing."],"exampleFix":"// before\ndefault:\n    throw new Error(`Unknown placeholder type: ${placeholder?.type} in ${link}`);\n// after\ndefault:\n    $el.replaceWith(placeholder?.data?.url ? `<a href=\"${placeholder.data.url}\">${placeholder.data.url}</a>` : '');","handlingStrategy":"type-guard","validationCode":"const KNOWN_PLACEHOLDER_TYPES = new Set(['markup','scribd','twitter']);\nfunction knownAfrPlaceholder(t) {\n  return t == null || KNOWN_PLACEHOLDER_TYPES.has(t);\n}","typeGuard":"function isKnownAfrPlaceholderType(t): t is 'markup'|'scribd'|'twitter'|undefined {\n  return t === undefined || t === 'markup' || t === 'scribd' || t === 'twitter';\n}","tryCatchPattern":"try {\n  return renderArticle(asset, link);\n} catch (e) {\n  if (e instanceof Error && /Unknown placeholder type/.test(e.message)) {\n    // strip unknown placeholders and retry, rather than failing the article\n    return asset.body.replace(/<x-placeholder[^>]*>[\\s\\S]*?<\\/x-placeholder>/g, '');\n  }\n  throw e;\n}","preventionTips":["New placeholder types are usually new embeds — report them upstream.","As a maintainer, default to replacing unknown placeholders with a link or empty string rather than throwing.","Pair the catch with telemetry so schema drift is visible."],"tags":["upstream-dependent","schema","rsshub","error-class-mismatch"],"backgroundTag":null,"analyzedSha":"bed535e0879dc71c5aff6f1e7bd1ac21ede40115","analyzedAt":"2026-08-12T19:29:35.364Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}