DIYgod/RSSHub · error · Error
Unknown placeholder type: ${placeholder?.type} in ${link}
Error message
Unknown placeholder type: ${placeholder?.type} in ${link} What it means
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.
Source
Thrown at lib/routes/afr/utils.ts:76
case 'linkExternal':
$el.replaceWith(`<a href="${placeholder.data.url}" target="_blank" rel="noopener">${placeholder.data.text}</a>`);
break;
case 'quote':
$el.replaceWith(placeholder.data.markup);
break;
case 'scribd':
$el.replaceWith(`<a href="${placeholder.data.url}" target="_blank" rel="noopener">View on Scribd</a>`);
break;
case 'twitter':
$el.replaceWith(`<a href="${placeholder.data.url}">${placeholder.data.url}</a>`);
break;
default:
throw new Error(`Unknown placeholder type: ${placeholder?.type} in ${link}`);
}
});
return $.html();
};
View on GitHub (pinned to bed535e087)
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.
Example fix
// before
default:
throw new Error(`Unknown placeholder type: ${placeholder?.type} in ${link}`);
// after
default:
$el.replaceWith(placeholder?.data?.url ? `<a href="${placeholder.data.url}">${placeholder.data.url}</a>` : ''); Defensive patterns
Strategy: type-guard
Validate before calling
const KNOWN_PLACEHOLDER_TYPES = new Set(['markup','scribd','twitter']);
function knownAfrPlaceholder(t) {
return t == null || KNOWN_PLACEHOLDER_TYPES.has(t);
} Type guard
function isKnownAfrPlaceholderType(t): t is 'markup'|'scribd'|'twitter'|undefined {
return t === undefined || t === 'markup' || t === 'scribd' || t === 'twitter';
} Try / catch
try {
return renderArticle(asset, link);
} catch (e) {
if (e instanceof Error && /Unknown placeholder type/.test(e.message)) {
// strip unknown placeholders and retry, rather than failing the article
return asset.body.replace(/<x-placeholder[^>]*>[\s\S]*?<\/x-placeholder>/g, '');
}
throw e;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: Upstream adds a new embeddable block; an article uses a feature not previously seen in the feed.
Related errors
- Unknown asset type: ${content.assetType} in ${item.link}
- Category not found
- Tag not found
- 日报数据不存在或为空
- Empty content: ${articleUrl}
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/bc1685d010f82ab7.
Report an issue: GitHub.