DIYgod/RSSHub · error
Unhandled card on ${link}: ${name}
Error message
Unhandled card on ${link}: ${name} What it means
The `default` arm of the `name` switch in `card2Html`. It fires when a Yuque `<card>` element has a `name` attribute not covered by any defined case (board, emoji, image, thirdparty, yuque, video, etc.). The message reports the document link and the unknown card name.
Source
Thrown at lib/routes/yuque/utils.ts:75
throw new Error(`Unhandled thirdparty on ${link}: ${elem.attr('alias')}`);
}
break;
case 'yuque':
if (value.mode === 'card') {
html = `<a href='${value.src}'>${value.detail.title}</a>`;
} else if (value.mode === 'embed') {
html = `<iframe src="${value.url}" width="100%" height="518"></iframe>`;
} else {
throw new Error(`Unhandled mode on ${link}: ${value.mode}`);
}
break;
case 'video':
// fake video src
html = `<video src='${value.videoId}'></video>`;
break;
default:
throw new Error(`Unhandled card on ${link}: ${name}`);
}
elem.replaceWith(html);
};
export { card2Html };
View on GitHub (pinned to bed535e087)
Solutions
- Take the `name` from the error message and add a `case` that maps it to the right HTML (often an `<img src='${value.src}'>` or `<a href='${value.src}'>` depending on the payload).
- If you cannot determine the right HTML yet, make the `default` arm non-fatal — replace the card with an empty string or a placeholder link so the rest of the document still renders.
- Add the new card name to the known list and open an upstream issue to track full support.
Example fix
// before
default:
throw new Error(`Unhandled card on ${link}: ${name}`);
// after (graceful fallback + new case)
case 'callout':
html = `<blockquote>${value.text ?? ''}</blockquote>`;
break;
default:
html = '';
elem.remove();
break; Defensive patterns
Strategy: try-catch
Validate before calling
const knownCardNames = new Set([
'board','emoji','flowchart2','image','math','mindmap','puml',
'bookmarkInline','bookmarklink','yuqueinline','checkbox','codeblock',
'diagram','file','localdoc','hr','label','mention','table',
'thirdparty','youku','yuque','video',
]);
function isKnownCard(name) {
return knownCardNames.has(name);
} Type guard
function isKnownCardName(name: string | undefined): boolean {
return typeof name === 'string' && KNOWN_CARD_NAMES.has(name);
} Try / catch
try {
card2Html(elem, link);
} catch (e) {
logger.warn(`Skipping unhandled yuque card '${elem.attr('name')}' on ${link}`);
elem.remove();
} Prevention
- Never let card2Html throw propagate out of the per-element loop — isolate each card's failure.
- Keep a fixture set of Yuque documents exercising every known card name.
- Log unknown card names at warn level so schema drift is visible without breaking feeds.
When it happens
Trigger: Yuque introduces a brand-new block/card type (e.g. a callout, a new diagram kind, an attachment variant) so the serialized card carries a `name` value absent from the switch.
Common situations: Yuque releases a new editor feature; an existing card is renamed; the document was authored with a newer Yuque editor than the route supports. The throw aborts rendering of that document's whole body.
Related errors
- Unhandled thirdparty on ${link}: ${elem.attr('alias')}
- Unhandled mode on ${link}: ${value.mode}
- Unknown type: ${contentItem.type}
- Unknown type: ${contentItem.type}
- Unknown type: ${item.type}
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/c95b6b201f64e050.
Report an issue: GitHub.