Quick answer: The autoload bus outlives its subscribers. Disconnect in _ExitTree, or use ConnectFlags.OneShot / WeakReference for handlers that should auto-detach.

An EventBus autoload exposes a Scored signal. Enemies subscribe in _Ready. After many waves, scoring 1 point fires the handler 50 times and throws on dead enemies — subscriptions leaked.

Always Disconnect

public override void _Ready()
{
    EventBus.Instance.Scored += OnScored;
}

public override void _ExitTree()
{
    EventBus.Instance.Scored -= OnScored;
}

The bus has a list of delegates — it doesn’t know your enemy was freed. Without -= it keeps calling the dead handler, which throws ObjectDisposedException.

Idempotent Disconnect

C# event -= on a missing handler silently no-ops — safe to call defensively. If you mix Godot’s Connect API, use Disconnect with the same Callable you connected.

OneShot When You Mean Once

For “wake me up exactly once” subscriptions (a level-complete listener), ConnectFlags.OneShot auto-disconnects after the first fire. No manual cleanup.

WeakReference for Optional Listeners

If the subscriber is “maybe alive”, wrap it in a WeakReference and skip the call when it’s gone. Heavier than just disconnecting; only use when you can’t.

Verifying

Spawn and destroy hundreds of enemies. The Scored event fires the number of times it should (one per alive listener), not N×. No disposed-object exceptions.

“The bus holds your delegate forever. Disconnect in _ExitTree — or use OneShot when one fire is the intent.”

Pair every += in _Ready with a -= in _ExitTree as a habit. The leak is invisible until it crashes far from the cause.