Quick answer: Check that your @rpc annotation mode matches who is calling (use any_peer if clients initiate), confirm the calling node’s path is identical on both peers’ scene trees, and make sure the node is already in the scene tree before you invoke rpc().
You added @rpc to a function, called rpc("my_function"), and… nothing happens on the other end. No error, no warning — just silence. RPC failures in Godot 4 are notoriously quiet, and there are several independent reasons they can silently drop. This post walks through each one so you can get your multiplayer working.
The Symptom
The local peer executes the call without errors, but the remote peer never triggers the function. You may observe:
- The host fires an RPC and clients don’t respond.
- A client fires an RPC that never arrives on the host.
- RPCs work in the editor’s local multiplayer test but fail in a real network game.
- Godot prints nothing — no “RPC rejected” message, no stack trace.
The lack of feedback is what makes this bug frustrating. Godot will silently drop an RPC if the authority check fails or the node path cannot be resolved on the receiver.
What Causes This
There are four primary causes, all of which result in the same empty silence:
1. Wrong @rpc mode or authority flag. The @rpc annotation accepts up to four positional parameters: mode, sync, transfer_mode, and transfer_channel. The mode parameter controls who is allowed to send this RPC. The options are authority (default — only the node’s multiplayer authority may send it) and any_peer (any connected peer may send it). If a client tries to call an RPC annotated with authority on a node the server owns, the call is silently rejected.
2. Node path mismatch between peers. Godot routes RPCs by node path in the scene tree. If the node is at /root/Game/Player on the host but /root/Lobby/Player on the client, the RPC cannot be delivered — the receiver cannot find the node.
3. Node not yet in the scene tree. Calling rpc() before the node has been added to the tree (e.g. inside _init() rather than _ready()) will fail because the multiplayer API has not registered the node’s path yet.
4. call_local omitted when the caller also needs to run the function. By default, rpc() sends to all other peers. If you also want the local peer to execute the function, you must add call_local to the annotation or call the function directly alongside rpc().
The Fix: Correct @rpc Annotation
Here is the full signature of the @rpc annotation in Godot 4:
# @rpc(mode, sync, transfer_mode, transfer_channel)
# mode: "authority" | "any_peer"
# sync: "call_remote" (default) | "call_local"
# transfer_mode: "unreliable" | "unreliable_ordered" | "reliable"
# Server-only RPC (only the authority can call this):
@rpc("authority", "call_local", "reliable")
func sync_game_state(state: Dictionary) -> void:
apply_state(state)
# Client-to-server RPC (any peer may send this):
@rpc("any_peer", "call_remote", "reliable")
func request_action(action: String) -> void:
var sender_id = multiplayer.get_remote_sender_id()
print("Action from peer: ", sender_id)
A common pattern: clients send requests via
any_peerRPCs, and the server sends state updates back viaauthorityRPCs. Mixing these up — usingauthorityfor a client-initiated call — is the single most common RPC bug in Godot 4 multiplayer projects.
The Fix: Node Path Alignment
Every peer must have the node at the same path in its scene tree for RPC routing to work. The safest approach is to instantiate multiplayer-relevant scenes under a consistent root:
# Bad: host adds player under /root/Game, client adds under /root/Lobby
# RPCs will be silently dropped because paths don't match.
# Good: both peers use the same scene structure
# /root/Game/Players/1 (host's player)
# /root/Game/Players/2 (client's player)
func spawn_player(peer_id: int) -> void:
var player = PLAYER_SCENE.instantiate()
player.name = str(peer_id) # makes path predictable
$Players.add_child(player)
player.set_multiplayer_authority(peer_id)
If you have a situation where the scene tree root differs between peers, use MultiplayerAPI.set_root_path() to tell the multiplayer API which node to treat as the “root” for path resolution:
# Tell the API to resolve paths relative to /root/Game
multiplayer.set_root_path(NodePath("/root/Game"))
# Now a node at /root/Game/Players/1 is routed as Players/1
# Both peers must call this with the same path.
The Fix: Targeting a Specific Peer with rpc_id()
When you need to send an RPC to exactly one peer rather than broadcasting, use rpc_id(). This bypasses the mode broadcast rules and delivers directly to the specified peer ID:
# Send only to the client whose peer_id is stored in `target_id`
rpc_id(target_id, "receive_item", item_data)
# The receiving function still needs @rpc, but mode doesn't
# restrict who can *receive* — only who can *send*.
@rpc("authority")
func receive_item(data: Dictionary) -> void:
print("Got item: ", data)
Checking Authority and Sender ID
When an RPC arrives on the server from a client, always validate the sender. multiplayer.get_remote_sender_id() returns the peer ID of whoever called the RPC during its execution. Compare this against get_multiplayer_authority() on the relevant node to confirm the caller is who they claim to be:
@rpc("any_peer", "call_remote", "reliable")
func move_to(pos: Vector2) -> void:
var sender = multiplayer.get_remote_sender_id()
# Only allow the peer who owns this node to move it
if sender != get_multiplayer_authority():
push_warning("Unauthorized move from peer " + str(sender))
return
global_position = pos
This pattern prevents cheating: a malicious client cannot move another player’s node by spoofing an RPC, because the server verifies the sender matches the node’s authority.
Ensure the Node Is in the Scene Tree First
RPCs can only be dispatched from nodes that are registered with the multiplayer API, which happens when they enter the scene tree. Calling rpc() in _init() or before add_child() completes will silently fail. Always trigger RPCs from _ready() or later:
func _ready() -> void:
# Safe: node is in the tree, RPC can be dispatched
if multiplayer.is_server():
rpc("announce_spawn", name)
func _init() -> void:
# Unsafe: node not in tree yet, RPC will be dropped
rpc("announce_spawn", name) # DON'T do this
Related Issues
See also: Fix: Godot MultiplayerSynchronizer Scene Not Syncing Properties.
See also: Fix: Cross-Scene Signal Communication in Godot.
Silent RPC failures are Godot’s way of saying: check your paths and your authority flags first.