Describe the bug
Disposing a <Portal> throws if the portal mount was externally cleared before Solid cleanup runs. This reproduces in Solid 1.x and still reproduces on Solid 2 next.
Your Example Website or App
https://stackblitz.com/edit/solidjs-templates-wvzy8wgj?file=src%2FApp.tsx
import { createSignal, Show, flush } from 'solid-js';
import { Portal } from '@solidjs/web';
const externalClearMount = document.createElement('div');
document.body.append(externalClearMount);
export default function App() {
const [open, setOpen] = createSignal(true);
const [result, setResult] = createSignal('not run');
return (
<main>
<button
onClick={() => {
try {
externalClearMount.textContent = '';
setOpen(false);
flush();
setResult('disposed without throwing');
} catch (error) {
setResult(String(error));
}
}}
>
clear mount then close portal
</button>
<p>{result()}</p>
<Show when={open()}>
<Portal mount={externalClearMount}>
<span>overlay</span>
</Portal>
</Show>
</main>
);
}
Steps to Reproduce the Bug or Issue
- Open the StackBlitz repro.
- Click
clear mount then close portal.
- Observe the rendered result.
NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node.
Expected behavior
If the mount was already externally cleared, dispose() should not throw.
Expected result:
disposed without throwing
Screenshots or Videos
No response
Platform
- OS: macOS
- Browser: Chrome
- Version: Solid 1.x and Solid 2
next
Additional context
Observed in Solid 1.x and on current Solid 2 next at d8921ac1:
- Closing after
mount.textContent = "" throws NotFoundError.
This is an edge case involving external DOM mutation, but Portal mount={...} is specifically for rendering into a DOM node outside the normal component tree. Integration hosts, third-party modal containers, tests, or shell apps can realistically empty that container before Solid disposes the Portal.
This appears related to Portal's marker-range cleanup. Cleanup calls removeChild without guarding whether the child is still in the mount.
Describe the bug
Disposing a
<Portal>throws if the portal mount was externally cleared before Solid cleanup runs. This reproduces in Solid 1.x and still reproduces on Solid 2next.Your Example Website or App
https://stackblitz.com/edit/solidjs-templates-wvzy8wgj?file=src%2FApp.tsx
Steps to Reproduce the Bug or Issue
clear mount then close portal.Expected behavior
If the mount was already externally cleared,
dispose()should not throw.Expected result:
Screenshots or Videos
No response
Platform
nextAdditional context
Observed in Solid 1.x and on current Solid 2
nextatd8921ac1:mount.textContent = ""throwsNotFoundError.This is an edge case involving external DOM mutation, but
Portal mount={...}is specifically for rendering into a DOM node outside the normal component tree. Integration hosts, third-party modal containers, tests, or shell apps can realistically empty that container before Solid disposes the Portal.This appears related to Portal's marker-range cleanup. Cleanup calls
removeChildwithout guarding whether the child is still in the mount.