Godot 4.3 Signals Not Firing - Connection and Binding Fix (How to Fix)
You connected a signal in Godot 4.3 but the connected function never runs when the signal is emitted. The game runs without errors, but the behavior you expected from the signal does not happen. This can be frustrating when you are sure the connection was made.
This guide explains why Godot 4.3 signals sometimes do not fire after connection and how to fix connection, binding, and timing issues. By the end, you will know how to connect signals correctly and verify they work.
The Problem
Common symptoms:
- Signal connected but callback never runs β You call
connect()and nothing happens when the signal is emitted. - Signal worked in Godot 3.x but not in 4.3 β Old connection style or node paths no longer work.
- Signal fires once then stops β Often due to scene change or node being freed.
- No error message β Connection appears to succeed but the callable is never invoked.
- Signal fires on wrong object β Callback runs on a different node than intended.
These usually point to how or when the signal was connected, or to the lifetime of the nodes involved.
Why This Happens
Connection timing and lifecycle
- The receiver or emitter is not ready when you connect. In Godot 4, both nodes should exist and, when possible, have had
_ready()run before you connect. - You connect in
_ready()but the emitting node is a child that is not ready yet, so the connection can fail or the emitter is invalid. - After a scene change, nodes from the old scene are freed and their signals are disconnected. If you keep a reference to an old node and emit from it, nothing will receive it.
Wrong connection target or callable
- You pass a string (e.g.
"method_name") instead of a Callable (e.g.method_nameorself.method_name). Godot 4 uses Callables; string-based connection is deprecated or not valid for the API you are using. - The callable is bound to the wrong object (e.g. a freed node) or the method does not exist on the node that receives the signal.
- Typo in method name β The method you pass to
connect()does not exist on the target object, so the callable is invalid.
Node path and references
- You use
get_node()or$NodePathand the path is wrong after a scene or node change, so you connect to the wrong node or to nothing. - You hold a reference to a node that gets freed (e.g. after changing scene), then emit or connect from that reference.
Binding and extra arguments
- In Godot 4 you use
.bind(args)for extra arguments. If you use the wrong number or order of arguments, the callback may not match the signal signature and can be skipped or error in a way that looks like "signal not firing." - Passing a callable that expects different parameters than the signal provides can cause runtime errors or no call.
Editor vs code
- You connected the signal in the Editor (Signals tab) but the node path or script method changed, so the connection points to a missing or wrong method.
- You connect in code but the node order or scene tree is different at runtime (e.g. instanced scene), so the emitter or receiver is not the one you expect.
Solution 1: Connect with Callables (Godot 4 Syntax)
In Godot 4 and 4.3, signals are connected using Callables, not strings.
Step 1: Use the Correct Connect Form
Correct (Callable):
# Connect to a method on self
emitter.signal_name.connect(_on_signal_name)
# Connect to a method on another node
emitter.signal_name.connect(target_node._on_signal_name)
# With extra arguments using bind()
emitter.signal_name.connect(_on_signal_name.bind(my_arg))
Incorrect (old or invalid):
# Do NOT rely on string method names for connect()
emitter.signal_name.connect("_on_signal_name") # Deprecated / may not work as expected
Step 2: Ensure the Method Exists and Matches
- The target method must exist on the object you pass (e.g.
selfortarget_node). - The method signature should match the signal (same number and types of parameters), or use
.bind()to supply extra arguments so the remaining parameters match the signal.
Verification: Add a print() at the start of the callback. Run the game and trigger the signal. If the print runs, the connection and emission work; if not, the problem is connection, timing, or node lifetime.
Solution 2: Fix Connection Timing (Use _ready() and Node Order)
Signals should be connected when both the emitter and the receiver exist and are in the tree. For many cases, connecting in _ready() is sufficient, but the order of _ready() calls depends on the scene tree (parent before children).
Step 1: Connect After Nodes Are Ready
Connect in _ready() and ensure you are not depending on a child that has not run its _ready() yet:
func _ready() -> void:
# If the emitter is a child, it already exists when parent's _ready() runs
var button = $Button
if button:
button.pressed.connect(_on_button_pressed)
Step 2: If the Emitter Is Created at Runtime
If you create the emitter node in code (e.g. instantiate() and add_child()`), connect after adding it to the tree so it is ready:
var new_node = scene.instantiate()
add_child(new_node)
# Connect after add_child so the node is in the tree and ready
new_node.signal_name.connect(_on_signal_name)
Verification: Again, use a print() in the callback to confirm it runs when you expect.
Solution 3: Do Not Rely on Freed Nodes
When you change scenes or remove nodes, they are freed and their signals no longer reach valid receivers. If you keep a reference to an old node and emit from it, nothing will happen.
Step 1: Connect and Emit Within the Same Scene Lifecycle
- Connect signals when both nodes are in the current scene tree.
- Do not keep references to nodes from a previous scene and expect their signals to work after a scene change.
Step 2: Use Scene Tree Lifecycle
If you need to react to scene changes, use the scene tree API (e.g. tree_exiting, or signals on the node that is not freed) instead of holding references to nodes that get freed.
Verification: After a scene change, do not call methods or emit on nodes from the old scene. If your logic depends on that, move the logic to a node that persists (e.g. autoload) or to the new scene.
Solution 4: Check Node Paths and References
Wrong node paths or stale references can make it seem like "signals don't fire."
Step 1: Resolve Emitter and Receiver Correctly
- Use
get_node()or$NodePathwith a path that is valid at the time you connect. - If the node is inside an instanced scene, the path must reflect the actual tree (e.g.
$SubScene/Buttonnot just$Button). - Print the node reference to debug:
print(emitter)andprint(receiver)to ensure they are non-null and the right types.
Step 2: Prefer Unique Names or Direct References
If you have dynamic or duplicated scenes, avoid fragile paths. Use unique names in the editor or store a direct reference when you instantiate:
var my_button = $SubScene/Button
my_button.pressed.connect(_on_button_pressed)
Verification: Ensure emitter and the connection target are the nodes you expect. A simple print() in the callback confirms the connection and emission.
Solution 5: Binding and Extra Arguments
If your callback needs extra arguments, use .bind() so the callable still matches the signalβs parameter list.
Step 1: Match the Signal Signature
Your callback can have more parameters than the signal if you bind the extra ones:
# Signal: emitted_with_one_arg(value)
# Callback: _on_signal(value, my_extra)
emitter.emitted_with_one_arg.connect(_on_signal.bind(my_extra))
func _on_signal(value: int, my_extra: String) -> void:
print(value, my_extra)
Step 2: Do Not Mismatch Parameter Count
If the signal emits two arguments and your callable expects one (and you did not bind one), the call can fail or not run. Adjust the callback or use .bind() so the remaining parameters match.
Verification: Call the callback manually from the editor or a test script with the same arguments the signal emits. If it runs when called directly but not when the signal fires, the issue is connection or emission.
Alternative Fixes
Reconnect in the editor: If you connected in the Editor and the script or node changed, remove the old connection and reconnect the signal to the correct method on the correct node.
Use Callable explicitly: If you are building the callable dynamically, use Callable(object, "method_name") and ensure object is valid and has that method.
Debug emission: Temporarily add print("emitting") where you emit the signal. If "emitting" prints but the callback does not run, the problem is the connection or the receiver. If "emitting" does not print, the problem is that the signal is never emitted.
Prevention Tips
- Always use Callables for
connect()in Godot 4/4.3; avoid string-based connection for new code. - Connect in
_ready()(or after adding runtime nodes) so both sides exist and are in the tree. - Avoid keeping references to freed nodes; do not emit or connect from nodes that have been removed or freed.
- Use
print()in callbacks during development to confirm signals fire. - Check the Signals tab in the editor for the node to see which signals exist and how they are connected.
Related Problems and Links
- For GDScript syntax or type errors, see GDScript Syntax Errors in Godot - Common Fixes.
- For Godot export or runtime issues, see Godot Black Screen After Export - How to Fix.
- For Unity event/callback issues, see Unity Scripts Not Executing - MonoBehaviour Issues (when available).
Official documentation:
- Godot 4.x Signals (check your Godot version).
Bookmark this fix for quick reference when debugging signals. If this article helped, share it with other Godot devs. If your signals still do not fire after trying these steps, double-check the Signals tab in the editor and the exact node/method you are connecting in code.