When multiplayer misbehaves, SpawnWeaver can tell you exactly what happened — on the client (SDK logging, debug reports) and on the server (session timelines, aggregated errors). This guide is your toolbox, plus checklists for the three most common failures.
SDK logging
SpawnWeaver.set_debug_enabled(true)
With debug enabled, the SDK prints every message it sends and receives, and every error, to the Godot output:
[SpawnWeaver] → room.create
[SpawnWeaver] ← room.created
[SpawnWeaver] ← room.player_joined
[SpawnWeaver] error rate-limited: Sending faster than the allowed rate…
You can also switch it on without code by adding debug=true to the [spawnweaver]
section of res://spawnweaver.cfg.
Debug reports and the Debug Bundle viewer
Every SDK client can produce a copyable diagnostic snapshot — SDK and Godot versions, connection status, server URL, player and room ids, latency, reconnect attempts, and ring buffers of the last 50 messages and last 10 errors:
print(SpawnWeaver.create_debug_report_string()) # pretty-printed JSON
Wire it to a debug key or a "Copy debug info" button in your bug-report UI:
func _input(event: InputEvent) -> void:
if event.is_action_pressed("copy_debug_report"):
DisplayServer.clipboard_set(SpawnWeaver.create_debug_report_string())
Paste the report into the dashboard's Debug Bundle viewer (/dashboard/debug) to inspect a player's state offline — perfect for playtester bug reports: "paste what the game copied to your clipboard".
The dashboard debugger
The Debugger hub in the dashboard explains why a session failed:
| Tool | Where | What it shows |
|---|---|---|
| Session inspector | /dashboard/sessions/{id} |
Per-connection timeline: connected → authenticated → every action → rejections → disconnected; plus IP, SDK + Godot versions, current room, auth status, disconnect reason |
| Error explorer | /dashboard/errors |
Protocol errors aggregated by code, with counts, affected sessions, and a suggested fix for each |
| Room & matchmaking inspectors | Debugger hub | A room's members, host, and metadata; the matchmaking queue's contents |
| Debug bundle viewer | /dashboard/debug |
Paste a client's create_debug_report_string() output |
| Live activity & logs | Debugger hub | Live connections/rooms and recent server logs |
The SDK reports its sdkVersion and engine version on connect, so the session
inspector can tell you a tester is on an old build.
The editor dock
The SpawnWeaver dock is the first stop for setup problems:
- Test connection — performs a real end-to-end connect with your saved key and server URL, from inside the editor.
- Live counts — shows your project's connected players and open rooms, refreshed every few seconds while the editor runs. If your game connects and the count rises, the pipeline works.
Simulating bad networks
SpawnWeaver.simulate_connection_loss()
Drops the socket as if the network blipped: auto-reconnect and room resume kick in
exactly as they would in production. Use it to test your reconnecting,
player_disconnected, and room_joined-resume handling without pulling cables.
Checklists
"Could not connect"
start() fails, or the dock's Test connection fails.
- Key: is
project_keyapk_…value with no spaces? (Not thesk_…secret.) - URL: hosted service → leave the Server field empty. Local server →
ws://127.0.0.1:5159/connect(notews://, notwss://— local dev has no TLS; hosted/production iswss://). - Server up? Local: is
./quickstart.ps1(or yourdotnet run) still running? Checkhttp://localhost:5159/health. - Project active? A deactivated project rejects the handshake with 401.
- Enable
set_debug_enabled(true)and read the close reason in the output; check the session (or its absence) in the dashboard's session inspector.
"Join failed"
room-not-found— the code is wrong, or the room expired (rooms with no connected members expire after ~60s; a server restart drops all rooms).room-full—max_playersreached; note players inside the disconnect grace window still hold seats.already-in-room— you're already in a room (one per connection);await SpawnWeaver.leave_room()first.not-connected— you calledjoin_room()beforestart()succeeded.
"Movement is choppy"
- Remote copies should have
interpolate = trueon theirSpawnSync(default). If you snap positions yourself in_process, you're fighting the interpolation. interpolation_speed: lower = smoother but laggier; try 10–16 for avatars.- Check
SpawnWeaver.latency_ms— with high ping, favor smoothness. - Watch the output for
rate-limitederrors: if other traffic (events, manual state calls) eats the budget,SpawnSyncupdates get dropped. Keepsend_rateat the default 8 and batch other messages. - Only the local copy should have
is_local = true— two senders for one entity producestate-forbiddenerrors and teleporting.
More symptom → fix tables in Troubleshooting.
Next
- Troubleshooting — symptom → cause → fix, with exact error codes
- Limits — the limit behind each limit error