Describe the bug
Looking into lifecycle internals for #18583 led me here. If a server render throws partway through, onDestroy callbacks registered by components that already ran are never called: #close_render is the only caller of #collect_on_destroy and is unreachable on the error path. The abort-signal cleanup in the same finally blocks does run (renderer.js:643, renderer.js:669), so getAbortSignal().addEventListener('abort', ...) fires on failed renders while onDestroy doesn't.
#10296 added server onDestroy so per-request resources get released, and a failed render is where skipping that hurts most, since errors tend to repeat across requests. If success-only cleanup is intended, I couldn't find it documented.
Affects both the sync and async (top-level await) render paths.
Reproduction
<!-- Parent.svelte -->
<script>
import { onDestroy, getAbortSignal } from 'svelte';
import Child from './Child.svelte';
let { fail } = $props();
onDestroy(() => console.log('onDestroy fired'));
getAbortSignal().addEventListener('abort', () => console.log('abort fired'));
</script>
{#if fail}<Child />{/if}
<!-- Child.svelte -->
<script>
throw new Error('boom');
</script>
render(Parent, { props: { fail: false } }) logs both callbacks. With fail: true it logs only abort fired.