hcengineering/platform · error
Token type `${node.type}` not supported by Markdown renderer
Error message
Token type `${node.type}` not supported by Markdown renderer What it means
The Markdown serializer's render() method dispatches to a per-node-type renderer looked up in this.nodes. If a node's type has no registered renderer, the serializer cannot produce Markdown for it and throws this error instead of silently emitting wrong output.
Source
Thrown at foundations/core/packages/text-markdown/src/serializer.ts:557
// :: (string, ?bool)
// Add the given text to the document. When escape is not `false`,
// it will be escaped.
text (text: string, escape = false): void {
const lines = text.split('\n')
for (let i = 0; i < lines.length; i++) {
const startOfLine = this.atBlank() || this.closed
this.write('')
this.out += escape ? this.esc(lines[i], startOfLine) : lines[i]
if (i !== lines.length - 1) this.out += '\n'
}
}
// :: (Node)
// Render the given node as a block.
render (node: MarkupNode, parent: MarkupNode, index: number): void {
if (this.nodes[node.type] === undefined) {
throw new Error('Token type `' + node.type + '` not supported by Markdown renderer')
}
this.nodes[node.type](this, node, parent, index)
}
// :: (Node)
// Render the contents of `parent` as block nodes.
renderContent (parent: MarkupNode): void {
nodeContent(parent).forEach((node: MarkupNode, i: number) => {
this.render(node, parent, i)
})
}
reorderMixableMark (state: InlineState, mark: MarkupMark, i: number, len: number): void {
for (let j = 0; j < state.active.length; j++) {
const other = state.active[j]
if (!this.marks[other.type].mixable || this.checkSwitchMarks(i, j, state, mark, other, len)) {
break
}View on GitHub (pinned to 63e28dc964)
Solutions
- Remove or convert unsupported node types before rendering (e.g. map them to supported paragraphs/text)
- Register a renderer for the node type in the serializer's nodes table
- Check document contents with a filter step that drops or rewrites unknown node types
Example fix
// before render(doc) // doc contains custom 'embed' node -> throws // after const filtered = doc.filter(n => supportedTypes.has(n.type)) render(filtered)
Defensive patterns
Strategy: validation
Validate before calling
const supported = new Set(['paragraph','heading','bulletList','orderedList','listItem','codeBlock','blockquote'])
if (!supported.has(node.type)) throw new Error(`node ${node.type} not renderable to markdown`) Type guard
function isRenderable(node: { type: string }, supported: Set<string>): boolean {
return supported.has(node.type)
} Try / catch
try {
serializer.render(node, parent, index)
} catch (e) {
if (e.message.includes('not supported by Markdown renderer')) {
return fallbackRender(node)
}
throw e
} Prevention
- Keep custom node types registered in the serializer's nodes table
- Run documents through a sanitizer that drops unknown node types before export
- Add a test that serializes every node type in your schema
When it happens
Trigger: Passing a document containing a node type the Markdown renderer does not support (e.g. a custom node, hard-break, or a node kind only valid in HTML/other renderers) to render(), called via renderContent, checkOpenMarks, or renderListItem.
Common situations: Custom node types added via plugins, documents round-tripped from other formats introducing unsupported nodes, or upgrading the document schema without updating renderer node registrations.
Related errors
AI-assisted analysis of hcengineering/platform@63e28dc964 (2026-08-29).
Data as JSON: /api/errors/8f12b1d6ebbea8ce.
Report an issue: GitHub.