diff --git a/apps/server/src/common/helpers/prosemirror/html-embed.spec.ts b/apps/server/src/common/helpers/prosemirror/html-embed.spec.ts
index 6b07ec0b..b48e9e73 100644
--- a/apps/server/src/common/helpers/prosemirror/html-embed.spec.ts
+++ b/apps/server/src/common/helpers/prosemirror/html-embed.spec.ts
@@ -92,6 +92,17 @@ describe('stripHtmlEmbedNodes', () => {
const result = stripHtmlEmbedNodes(doc);
expect(result).toEqual(doc);
});
+
+ it('neutralizes a root node that is itself an htmlEmbed', () => {
+ // Defensive: the PM root is always a `doc`, so this is unreachable in normal
+ // use, but the helper must still never return a bare htmlEmbed.
+ const root = {
+ type: 'htmlEmbed',
+ attrs: { source: '' },
+ };
+ const result = stripHtmlEmbedNodes(root);
+ expect(hasHtmlEmbedNode(result)).toBe(false);
+ });
});
describe('canAuthorHtmlEmbed', () => {
diff --git a/apps/server/src/common/helpers/prosemirror/html-embed.util.ts b/apps/server/src/common/helpers/prosemirror/html-embed.util.ts
index f1d0b6e5..aa5d579d 100644
--- a/apps/server/src/common/helpers/prosemirror/html-embed.util.ts
+++ b/apps/server/src/common/helpers/prosemirror/html-embed.util.ts
@@ -22,6 +22,15 @@ export function stripHtmlEmbedNodes(pmJson: T): T {
const node = pmJson as unknown as JSONContent;
+ // Defensive root-type check: if the ROOT node is itself an htmlEmbed, the
+ // children-filtering below could never drop it, so a bare htmlEmbed would be
+ // returned as-is. This branch is unreachable in normal use (the PM document
+ // root is always a `doc`) and exists only to make the helper total — a bare
+ // htmlEmbed can never be returned by this function.
+ if (node.type === HTML_EMBED_NODE_NAME) {
+ return { type: 'doc', content: [] } as unknown as T;
+ }
+
if (Array.isArray(node.content)) {
const filtered: JSONContent[] = [];
for (const child of node.content) {