diff --git a/packages/compiler-dom/src/index.ts b/packages/compiler-dom/src/index.ts
index 809f3708023..a3a738a8fb1 100644
--- a/packages/compiler-dom/src/index.ts
+++ b/packages/compiler-dom/src/index.ts
@@ -19,14 +19,13 @@ import { transformShow } from './transforms/vShow'
 import { transformTransition } from './transforms/Transition'
 import { stringifyStatic } from './transforms/stringifyStatic'
 import { ignoreSideEffectTags } from './transforms/ignoreSideEffectTags'
-import { validateHtmlNesting } from './transforms/validateHtmlNesting'
 import { extend } from '@vue/shared'
 
 export { parserOptions }
 
 export const DOMNodeTransforms: NodeTransform[] = [
   transformStyle,
-  ...(__DEV__ ? [transformTransition, validateHtmlNesting] : []),
+  ...(__DEV__ ? [transformTransition] : []),
 ]
 
 export const DOMDirectiveTransforms: Record<string, DirectiveTransform> = {
diff --git a/packages/compiler-dom/__tests__/transforms/validateHtmlNesting.spec.ts b/packages/compiler-ssr/__tests__/validateHtmlNesting.spec.ts
similarity index 73%
rename from packages/compiler-dom/__tests__/transforms/validateHtmlNesting.spec.ts
rename to packages/compiler-ssr/__tests__/validateHtmlNesting.spec.ts
index ad9f917137e..f5da4d36767 100644
--- a/packages/compiler-dom/__tests__/transforms/validateHtmlNesting.spec.ts
+++ b/packages/compiler-ssr/__tests__/validateHtmlNesting.spec.ts
@@ -1,4 +1,5 @@
-import { type CompilerError, compile } from '../../src'
+import type { CompilerError } from '@vue/compiler-core'
+import { compile } from '@vue/compiler-ssr'
 
 describe('validate html nesting', () => {
   it('should warn with p > div', () => {
@@ -7,7 +8,7 @@ describe('validate html nesting', () => {
       onWarn: e => (err = e),
     })
     expect(err).toBeDefined()
-    expect(err!.message).toMatch(`<div> cannot be child of <p>`)
+    expect(err!.message).toMatch(`<div> as a child of <p>`)
   })
 
   it('should not warn with select > hr', () => {
diff --git a/packages/compiler-dom/src/htmlNesting.ts b/packages/compiler-ssr/src/htmlNesting.ts
similarity index 92%
rename from packages/compiler-dom/src/htmlNesting.ts
rename to packages/compiler-ssr/src/htmlNesting.ts
index cb0a7626d15..cc5b9a6d622 100644
--- a/packages/compiler-dom/src/htmlNesting.ts
+++ b/packages/compiler-ssr/src/htmlNesting.ts
@@ -5,10 +5,17 @@
  * To avoid runtime dependency on validate-html-nesting
  * This file should not change very often in the original repo
  * but we may need to keep it up-to-date from time to time.
+ *
+ * The parent-child nesting is considered valid if the Browser
+ * does not modify it, regardless of whether or not the HTML spec
+ * considers it valid or invalid. So, the library is purely for
+ * detecting the kind of element nesting which result in altered DOM.
+ *
  */
 
 /**
- * returns true if given parent-child nesting is valid HTML
+ * returns true if given parent-child nesting is not known to result
+ * in an altered DOM
  */
 export function isValidHTMLNesting(parent: string, child: string): boolean {
   // if we know the list of children that are the only valid children for the given parent
diff --git a/packages/compiler-ssr/src/index.ts b/packages/compiler-ssr/src/index.ts
index f8a686555e8..a88045c689f 100644
--- a/packages/compiler-ssr/src/index.ts
+++ b/packages/compiler-ssr/src/index.ts
@@ -27,6 +27,7 @@ import { ssrTransformModel } from './transforms/ssrVModel'
 import { ssrTransformShow } from './transforms/ssrVShow'
 import { ssrInjectFallthroughAttrs } from './transforms/ssrInjectFallthroughAttrs'
 import { ssrInjectCssVars } from './transforms/ssrInjectCssVars'
+import { validateHtmlNesting } from './transforms/validateHtmlNesting'
 
 export function compile(
   source: string | RootNode,
@@ -66,6 +67,7 @@ export function compile(
       ssrTransformComponent,
       trackSlotScopes,
       transformStyle,
+      ...(__DEV__ ? [validateHtmlNesting] : []),
       ...(options.nodeTransforms || []), // user transforms
     ],
     directiveTransforms: {
diff --git a/packages/compiler-dom/src/transforms/validateHtmlNesting.ts b/packages/compiler-ssr/src/transforms/validateHtmlNesting.ts
similarity index 85%
rename from packages/compiler-dom/src/transforms/validateHtmlNesting.ts
rename to packages/compiler-ssr/src/transforms/validateHtmlNesting.ts
index 540c0c25871..7e40e8d3753 100644
--- a/packages/compiler-dom/src/transforms/validateHtmlNesting.ts
+++ b/packages/compiler-ssr/src/transforms/validateHtmlNesting.ts
@@ -16,8 +16,8 @@ export const validateHtmlNesting: NodeTransform = (node, context) => {
     !isValidHTMLNesting(context.parent.tag, node.tag)
   ) {
     const error = new SyntaxError(
-      `<${node.tag}> cannot be child of <${context.parent.tag}>, ` +
-        'according to HTML specifications. ' +
+      `<${node.tag}> as a child of <${context.parent.tag}> ` +
+        'might result in the browser modifying the DOM. ' +
         'This can cause hydration errors or ' +
         'potentially disrupt future functionality.',
     ) as CompilerError
diff --git a/packages/server-renderer/src/helpers/ssrCompile.ts b/packages/server-renderer/src/helpers/ssrCompile.ts
index 8412a65e843..6a2e986794c 100644
--- a/packages/server-renderer/src/helpers/ssrCompile.ts
+++ b/packages/server-renderer/src/helpers/ssrCompile.ts
@@ -67,8 +67,8 @@ export function ssrCompile(
     return cached
   }
 
-  finalCompilerOptions.onError = (err: CompilerError) => {
-    if (__DEV__) {
+  if (__DEV__) {
+    const compilationErrorHandler = (err: CompilerError) => {
       const message = `[@vue/server-renderer] Template compilation error: ${err.message}`
       const codeFrame =
         err.loc &&
@@ -78,7 +78,11 @@ export function ssrCompile(
           err.loc.end.offset,
         )
       warn(codeFrame ? `${message}\n${codeFrame}` : message)
-    } else {
+    }
+    finalCompilerOptions.onWarn = compilationErrorHandler
+    finalCompilerOptions.onError = compilationErrorHandler
+  } else {
+    finalCompilerOptions.onError = (err: CompilerError) => {
       throw err
     }
   }