DIYgod/RSSHub · error · Error
Unhandled mark type
Error message
Unhandled mark type: ${mark.type} What it means
Thrown (bare Error) inside the recursive render() function of the Netflix newsroom route when a rich-text 'text' node has a mark whose type is not one of the four handled: bold, italic, underline, strikethrough. The Netflix/Contentful-style document model added (or returned) an unrecognised inline mark (e.g. 'code', 'superscript', 'subscript', 'comment'), and the default branch of the switch throws instead of rendering or skipping it.
Solutions
- Patch the switch to handle (or ignore) the new mark type — add cases for the missing types, and make the default return the text unmodified instead of throwing, so future marks don't break the feed.
- Inspect the failing article's JSON (fetch the upstream payload) to see exactly which mark.type triggered it.
- If you only need a quick unblock, default to returning `text` (no formatting) for unknown marks.
Example fix
// before
default:
throw new Error(`Unhandled mark type: ${mark.type}`);
// after — render known extra marks, gracefully ignore unknown ones
case 'code':
text = `<code>${text}</code>`;
break;
case 'superscript':
text = `<sup>${text}</sup>`;
break;
case 'subscript':
text = `<sub>${text}</sub>`;
break;
default:
// unknown mark: keep the text, do not fail the whole feed
break; Defensive patterns
Strategy: validation
Validate before calling
// Defensive: never throw on an unknown mark; render known ones, ignore the rest.
for (const mark of node.marks ?? []) {
switch (mark.type) {
case 'bold': text = `<strong>${text}</strong>`; break;
case 'italic': text = `<em>${text}</em>`; break;
case 'underline': text = `<u>${text}</u>`; break;
case 'strikethrough': text = `<s>${text}</s>`; break;
case 'code': text = `<code>${text}</code>`; break;
default: break; // ignore unknown marks
}
} Type guard
const KNOWN_MARKS = new Set(['bold', 'italic', 'underline', 'strikethrough', 'code']);
function isKnownMark(mark: any): boolean {
return !!mark && typeof mark.type === 'string' && KNOWN_MARKS.has(mark.type);
} Prevention
- Never throw from a recursive rich-text renderer's default branch — degrade gracefully instead.
- Pin the renderer to a known CMS schema version and log unknown node/mark types for awareness without failing.
- Add tests with sample documents containing exotic marks to prevent regressions.
When it happens
Trigger: While rendering an article's rich-text body, a text node carries node.marks = [{type: 'code'}] (or any non-handled type). The switch falls through to default and throws, failing the whole feed even though only one article uses the new mark. Most likely after Netflix/CMS adds a new formatting option.
Common situations: Netflix's CMS introduces a new text decoration; an article copy-pasted from another tool carries an unusual mark; a Contentful schema upgrade adds marks the renderer doesn't know.
Related errors
- Unhandled node type
- Expected ' ' property not found in pageProps for category
- Failed to find __NEXT_DATA__ script tag in page
- Failed to parse __NEXT_DATA__ JSON
- Unknown handled type
AI-assisted analysis of DIYgod/RSSHub@bed535e087 (2026-08-12).
Data as JSON: /api/errors/b28e461092594e60.
Report an issue: GitHub.
Appendix: source
Thrown at lib/routes/netflix/newsroom.ts:142
if (!node.marks || node.marks.length === 0) {
return text;
}
for (const mark of node.marks) {
switch (mark.type) {
case 'bold':
text = `<strong>${text}</strong>`;
break;
case 'italic':
text = `<em>${text}</em>`;
break;
case 'underline':
text = `<u>${text}</u>`;
break;
case 'strikethrough':
text = `<s>${text}</s>`;
break;
default:
throw new Error(`Unhandled mark type: ${mark.type}`);
}
}
return text;
}
case 'hyperlink': {
const href = node.data?.uri || '#';
const innerHTML = node.content?.map((c) => render(c)).join('') || '';
return `<a href="${href}" target="_blank" rel="noopener noreferrer">${innerHTML}</a>`;
}
case 'embedded-asset-block': {
const file = Object.values<any>(node.data?.file)[0];
if (!file || !file.url) {
return '';
}
const url = file.url.startsWith('//') ? 'https:' + file.url : file.url;
const contentType = file.contentType || '';View on GitHub (pinned to bed535e087)