Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead in Godot 4

By Eduardo Orellana · Updated

The physics server is in the middle of reporting overlaps, and a body_entered handler tried to change collision state during it. $Shape.disabled = true inside body_entered prints Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead. Defer the change: $Shape.set_deferred("disabled", true).

AppImage, x86_64. Ubuntu 22.04, Debian 12, Fedora 39 or newer.

Intel or AMD Chromebook, with Linux turned on.

Download for macOSDownload for Windows

What Godot is checking

Area and body signals such as body_entered are emitted while the physics server flushes its queries, walking the list of overlaps it found this step. Changing a shape, a layer or monitoring then would change that list under it, so the server refuses with this error and leaves the state as it was.

set_deferred() and call_deferred() apply the change at idle time, after the flush, which is what the message asks for. The shape is then disabled from the next physics step.

Reproduce it

A coin Area2D that disables its own shape when the overlapping player enters.

extends Area2D

func _ready() -> void:
	body_entered.connect(_on_body_entered)

func _on_body_entered(body: Node2D) -> void:
	print("picked up by ", body.name)
	$Shape.disabled = true
	print("after")

What Godot 4.7.2 prints

Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

picked up by Player
ERROR: Can't change this state while flushing queries. Use call_deferred() or set_deferred() to change monitoring state instead.
   at: area_set_shape_disabled (modules/godot_physics_2d/godot_physics_server_2d.cpp:354)
   GDScript backtrace (most recent call first):
       [0] _on_body_entered (res://answers/cant-change-this-state-while-flushing-queries/repro.gd:8)
after

Fix it

The same coin, deferring the change.

extends Area2D

func _ready() -> void:
	body_entered.connect(_on_body_entered)

func _on_body_entered(body: Node2D) -> void:
	print("picked up by ", body.name)
	$Shape.set_deferred("disabled", true)
	await get_tree().process_frame
	print("disabled: ", $Shape.disabled)

What the fixed script prints

Godot Engine v4.7.2.stable.mono.official.ed1daf0bf - https://godotengine.org

picked up by Player
disabled: true

Adding or freeing physics nodes in the callback

Spawning a body with add_child(), or changing monitoring, collision_layer or a shape inside body_entered or area_entered, hits the same guard. Use add_child.call_deferred(), set_deferred(), or queue_free(), which already waits for the end of the frame.

Verified on Godot 4.7.2

Both scripts on this page were run headless on Godot 4.7.2 (4.7.2.stable.mono.official.ed1daf0bf) on 18 October 2026, and the output above is what Godot printed, unedited.

Where the check lives in Godot's source: [godot_physics_server_2d.cpp line 41, the message](https://github.com/godotengine/godot/blob/4.7.2-stable/modules/godot_physics_2d/godot_physics_server_2d.cpp#L41), [godot_physics_server_2d.cpp line 354, the check in area_set_shape_disabled](https://github.com/godotengine/godot/blob/4.7.2-stable/modules/godot_physics_2d/godot_physics_server_2d.cpp#L354).

Questions

Is queue_free() safe inside body_entered?
Yes. It frees the node at the end of the frame, after the physics flush.
Does the same happen in 3D?
Yes. The 3D physics server has the same guard and the same message for Area3D and its shapes.