docs/solutions/logic-errors/2026-03-14-markdown-incomplete-mdx-fallback-drops-void-blocks.md
markdownToSlateNodesSafely is the recovery path when full markdown deserialization fails and the input ends with incomplete MDX.
That fallback already handled two sane cases:
But the void-block case was wrong. If the complete prefix ended in a void element like a horizontal rule, the function returned only the fallback paragraph and threw away the already-parsed nodes.
The void-node branch returned:
return [newBlock];
That replaced the full completeNodes array instead of preserving it.
Append the fallback paragraph after the complete nodes:
if (ElementApi.isElement(lastBlock) && editor.api.isVoid(lastBlock)) {
return [...completeNodes, newBlock];
}
Now the safe fallback keeps the parsed prefix and still exposes the incomplete MDX tail as literal text.
These checks passed:
bun test packages/markdown/src/lib/deserializer/utils/markdownToSlateNodesSafely.spec.tsx
bun test packages/markdown/src
bun run test:slowest -- --top 15 packages/markdown/src
The package build lane was blocked by an external tooling issue unrelated to this fix:
TypeError [ERR_INVALID_ARG_VALUE]: ... node:util.styleText ... Received [ 'underline', 'gray' ]
When a fallback path combines “complete parsed output” with “literal recovery output,” add one test for each final-block shape:
That catches the easy mistake where the recovery branch accidentally replaces the result instead of extending it.