Quick answer: Godot disconnects normal method connections automatically when either side is freed, but lambdas that capture a freed node, deferred calls, and coroutines awaiting on a freed object are not protected. Prefer queue_free() over free(), check is_instance_valid() before touching saved references, and do not await signals of objects that may be freed first.
An enemy dies, and a moment later the console fills with errors about a previously freed instance — or a cutscene silently stops because the await it was waiting on never comes back. Both come from code that still holds on to an object after it is gone.
What Godot already handles
When an Object is freed, every signal connection to or from it that targets a method on an Object is removed. Emitting a signal after its listener was freed is therefore safe in the common case. The trouble starts in the places the engine cannot see.
Case 1: lambdas capturing a freed node
A lambda belongs to the script that created it, not to the nodes it mentions:
func _ready():
var enemy := $Enemy
GameEvents.wave_ended.connect(func(): enemy.celebrate())
When enemy is freed, the connection survives (its owner is this script), and the next wave_ended calls a method on a freed instance. Connect a method on the enemy itself, or guard the lambda:
GameEvents.wave_ended.connect(func():
if is_instance_valid(enemy):
enemy.celebrate())
Case 2: stored references
Arrays and variables keep references to freed nodes; they do not become null. Before using a saved node, check is_instance_valid(node). For nodes about to be deleted, node.is_queued_for_deletion() tells you to stop using it now.
Case 3: free() in the middle of processing
free() deletes immediately, even if the node is still inside a signal handler, a physics callback or a loop over children. Use queue_free(), which deletes at the end of the frame when nothing is using the node.
Case 4: await on a freed object
await $Boss.died # boss is queue_free()d by something else first
start_next_phase() # never runs
If the object emitting the signal is freed before emitting, the coroutine waits forever. If the object running the coroutine is freed while waiting, Godot reports that the function resumed after its instance was gone. Make the emitter emit *before* freeing itself, or wait on something that outlives both, such as an autoload signal or tree_exited:
# in Boss.gd
func die():
died.emit()
queue_free()
Case 5: tweens and timers on dead nodes
A Tween created with create_tween() is bound to the node that created it and stops when that node leaves the tree. A Tween from get_tree().create_tween() is not bound, so it keeps animating properties of a freed node unless you call bind_node(). SceneTreeTimers are also not bound; check validity in their timeout handler.
Finding the culprit
The error names the method that was called. Reproduce it with the editor's debugger attached and read the Stack Frames panel: the frame that made the call is the code still holding the stale reference.