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.
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)
afterFix 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: trueAdding 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.
Related
- Parent node is busy setting up children, add_child() failed
- Signal is already connected to given callable
- Every verified Godot 4 answer
- Area in Godot 4: it is Area3D now
- CollisionShape in Godot 4: it is CollisionShape3D now
- How to disable and enable a node in Godot 4: process_mode
- How to change scenes in Godot 4: change_scene_to_file()
- Can't add child '…' to '…', already has a parent '…' in Godot 4
Flockbay's agent reads Godot's debugger output and fixes errors like this one in your project, on the official Godot.
Download Flockbay free