diff --git a/packages/runtime-core/__tests__/components/Suspense.spec.ts b/packages/runtime-core/__tests__/components/Suspense.spec.ts
index 92638cc6ba3..c986ffdd796 100644
--- a/packages/runtime-core/__tests__/components/Suspense.spec.ts
+++ b/packages/runtime-core/__tests__/components/Suspense.spec.ts
@@ -1690,6 +1690,46 @@ describe('Suspense', () => {
expect(serializeInner(root)).toBe(`
sync
`)
})
+ // #6416 follow up
+ test('Suspense patched during HOC async component re-mount', async () => {
+ const key = ref('k')
+ const data = ref('data')
+
+ const Async = defineAsyncComponent({
+ render() {
+ return h('div', 'async')
+ }
+ })
+
+ const Comp = {
+ render() {
+ return h(Async, { key: key.value })
+ }
+ }
+
+ const root = nodeOps.createElement('div')
+ const App = {
+ render() {
+ return h(Suspense, null, {
+ default: h(Comp, { data: data.value })
+ })
+ }
+ }
+ render(h(App), root)
+ expect(serializeInner(root)).toBe(``)
+
+ await Promise.all(deps)
+
+ // async mounted, but key change causing a new async comp to be loaded
+ key.value = 'k1'
+ await nextTick()
+
+ // patch the Suspense
+ // should not throw error due to Suspense vnode.el being null
+ data.value = 'data2'
+ await Promise.all(deps)
+ })
+
describe('warnings', () => {
// base function to check if a combination of slots warns or not
function baseCheckWarn(
diff --git a/packages/runtime-core/src/componentRenderUtils.ts b/packages/runtime-core/src/componentRenderUtils.ts
index 38a9e8d19d8..2be51a22743 100644
--- a/packages/runtime-core/src/componentRenderUtils.ts
+++ b/packages/runtime-core/src/componentRenderUtils.ts
@@ -428,6 +428,7 @@ export function updateHOCHostEl(
{ vnode, parent }: ComponentInternalInstance,
el: typeof vnode.el // HostNode
) {
+ if (!el) return
while (parent) {
const root = parent.subTree
if (root.suspense && root.suspense.activeBranch === vnode) {