Summary
Hosting (and joining) custom games fails: the client hangs at "connecting" forever. Matchmaker games work normally.
With client TRACE logging enabled I captured the full lobby protocol in plaintext. The client sends {"command":"GameState","args":["Lobby"],"target":"game"} correctly, the websocket is demonstrably healthy in both directions, but the server never responds with HostGame and never transitions the game out of state: closed / hosted_at: null.
Because this only affects init_mode: 0 (custom) games and not matchmaker (init_mode: 1, which does not require the server→client HostGame/JoinGame GPGNet command), the problem is isolated to the server's handling of the GameState Lobby relay for custom games.
Environment
- Client version:
2026.4.1 (downlords-faf-client)
- Affected accounts:
RaidenBoson (id 454005) and ASoft (id 450602)
- Reproduced on two different machines, on two different accounts, and over a VPN (entirely different network path)
- Windows 11
Reproduction
Click "Create Game" with any map/settings. The game launches, reaches GameState Lobby, and the lobby never opens.
Captured protocol trace
Third of three consecutive attempts (client logLevel: TRACE). Tokens are masked by the client itself.
00:47:02.314 Outbound: {"command":"game_host","mapname":"dualgap_adaptive.v0014","title":"Chill Game",
"mod":"faf","options":[],"access":"public","version":0,"password":null,
"visibility":"public","rating_min":null,"rating_max":null,
"enforce_rating_range":false}
00:47:02.437 Inbound: {"command":"game_launch","args":["/numgames",814],"uid":27459407,"mod":"faf",
"name":"Chill Game","init_mode":0,"game_type":"custom","rating_type":"global"}
00:47:03.147 Inbound: {"command":"game_info","uid":27459407,"title":"Chill Game","state":"closed",
"mapname":"dualgap_adaptive.v0014","host":"RaidenBoson","num_players":0,
"max_players":12,"hosted_at":null,"launched_at":null,"teams":{}}
00:47:35.902 Outbound: {"command":"GameState","args":["Idle"],"target":"game"}
00:47:36.116 Outbound: {"command":"GameState","args":["Lobby"],"target":"game"}
(no HostGame; no further game_info for uid 27459407, ever)
The client-side emit is complete — the message is serialized and written, not dropped internally:
00:47:36.116 TRACE c.f.commons.lobby.FafLobbyClient : Sending message of type class com.faforever.commons.lobby.GpgGameOutboundMessage
00:47:36.116 TRACE c.f.commons.lobby.FafLobbyClient : Outbound message: {"command":"GameState","args":["Lobby"],"target":"game"}
The connection is healthy — this is not a dropped message
Counting inbound/outbound traffic after the GameState Lobby relay at 00:47:36, over the following ~6 minutes on the same websocket:
| Message |
Count |
game_info (other players' games) |
503 |
player_info |
145 |
matchmaker_info |
43 |
ping (server → client) |
8 |
pong (client → server) |
8 |
game_info for our own uid 27459407 |
0 |
The server keeps pinging and the client keeps ponging, and the session is never timed out — so client→server frames are reaching the server. The server simply never acts on the GameState Lobby message and never broadcasts another update for the game it just created.
What has been ruled out
Request contents. Three consecutive attempts varying game_host fields, all failing identically:
astro_crater_battles_4x4_rich_huge.v0004, rating_min: 900, rating_max: 3000, enforce_rating_range: true
astro_crater_battles_4x4_rich_huge_by_lisnesta.v0004, same rating settings
dualgap_adaptive.v0014, rating_min: null, rating_max: null, enforce_rating_range: false
All three maps are installed locally, and dualgap_adaptive.v0014 was being used by 69 other open games at the time.
Client side. The TRACE capture shows correct serialization and emission of GpgGameOutboundMessage.
ICE adapter. Connects, sends CreateLobby, receives GameState Lobby from the game, and relays it to the client correctly:
Sent GPGNet message: CreateLobby 0 42410 RaidenBoson 454005 1
Received GPGNet message: GameState Lobby
Sending Notification: {"method":"onGpgNetMessageReceived","params":["GameState",["Lobby"]],"jsonrpc":"2.0"}
Network / local environment. Matchmaker games work over the identical websocket, TLS session, ICE adapter and TURN relay. Also independently checked and excluded: DNS, MTU/PMTU, IPv6, packet loss, firewall, antivirus, Windows port reservations, ephemeral port exhaustion, and stale/zombie game processes. A clean client reinstall did not help.
Account / machine. Two accounts, two machines, and a VPN all reproduce it.
Failure occurs in windows, not at random
Hourly attempt/success counts for one day, taken from ice-adapter.log by counting Sent GPGNet message: CreateLobby (attempt) against Sent GPGNet message: HostGame (server responded):
| Hour |
Attempts |
Successes |
| 00 |
11 |
6 |
| 01 |
10 |
0 |
| 02 |
1 |
0 |
| 03 |
9 |
0 |
| 04 |
1 |
0 |
| 11 |
6 |
0 |
| 12 |
10 |
0 |
| 13 |
34 |
8 |
| 14 |
12 |
0 |
| 18 |
2 |
0 |
| 19 |
13 |
0 |
| 20 |
10 |
1 |
| 21 |
14 |
0 |
| 22 |
7 |
0 |
| 23 |
5 |
1 |
Inside a working window, CreateLobby and HostGame land in the same second, repeatedly. Outside one, it is 100% failure for hours. Nothing changes client-side across those boundaries.
Lifetime totals across all available logs: 266 custom-game attempts → 41 HostGame + 9 JoinGame returned.
Speculation
The windowed pattern would be consistent with the lobby connection being balanced across multiple server instances, where some instances have stuck or broken game-service state — leaving a client bound to a bad instance for the life of the websocket connection. I have no visibility into the server side to confirm this.
Happy to provide
Full TRACE client.log, ice-adapter.log, and game logs for any of the affected game UIDs (27459347, 27459382, 27459407) on request.
Summary
Hosting (and joining) custom games fails: the client hangs at "connecting" forever. Matchmaker games work normally.
With client TRACE logging enabled I captured the full lobby protocol in plaintext. The client sends
{"command":"GameState","args":["Lobby"],"target":"game"}correctly, the websocket is demonstrably healthy in both directions, but the server never responds withHostGameand never transitions the game out ofstate: closed/hosted_at: null.Because this only affects
init_mode: 0(custom) games and not matchmaker (init_mode: 1, which does not require the server→clientHostGame/JoinGameGPGNet command), the problem is isolated to the server's handling of theGameState Lobbyrelay for custom games.Environment
2026.4.1(downlords-faf-client)RaidenBoson(id454005) andASoft(id450602)Reproduction
Click "Create Game" with any map/settings. The game launches, reaches
GameState Lobby, and the lobby never opens.Captured protocol trace
Third of three consecutive attempts (client
logLevel: TRACE). Tokens are masked by the client itself.The client-side emit is complete — the message is serialized and written, not dropped internally:
The connection is healthy — this is not a dropped message
Counting inbound/outbound traffic after the
GameState Lobbyrelay at 00:47:36, over the following ~6 minutes on the same websocket:game_info(other players' games)player_infomatchmaker_infoping(server → client)pong(client → server)game_infofor our own uid 27459407The server keeps pinging and the client keeps ponging, and the session is never timed out — so client→server frames are reaching the server. The server simply never acts on the
GameState Lobbymessage and never broadcasts another update for the game it just created.What has been ruled out
Request contents. Three consecutive attempts varying
game_hostfields, all failing identically:astro_crater_battles_4x4_rich_huge.v0004,rating_min: 900,rating_max: 3000,enforce_rating_range: trueastro_crater_battles_4x4_rich_huge_by_lisnesta.v0004, same rating settingsdualgap_adaptive.v0014,rating_min: null,rating_max: null,enforce_rating_range: falseAll three maps are installed locally, and
dualgap_adaptive.v0014was being used by 69 other open games at the time.Client side. The TRACE capture shows correct serialization and emission of
GpgGameOutboundMessage.ICE adapter. Connects, sends
CreateLobby, receivesGameState Lobbyfrom the game, and relays it to the client correctly:Network / local environment. Matchmaker games work over the identical websocket, TLS session, ICE adapter and TURN relay. Also independently checked and excluded: DNS, MTU/PMTU, IPv6, packet loss, firewall, antivirus, Windows port reservations, ephemeral port exhaustion, and stale/zombie game processes. A clean client reinstall did not help.
Account / machine. Two accounts, two machines, and a VPN all reproduce it.
Failure occurs in windows, not at random
Hourly attempt/success counts for one day, taken from
ice-adapter.logby countingSent GPGNet message: CreateLobby(attempt) againstSent GPGNet message: HostGame(server responded):Inside a working window,
CreateLobbyandHostGameland in the same second, repeatedly. Outside one, it is 100% failure for hours. Nothing changes client-side across those boundaries.Lifetime totals across all available logs: 266 custom-game attempts → 41
HostGame+ 9JoinGamereturned.Speculation
The windowed pattern would be consistent with the lobby connection being balanced across multiple server instances, where some instances have stuck or broken game-service state — leaving a client bound to a bad instance for the life of the websocket connection. I have no visibility into the server side to confirm this.
Happy to provide
Full TRACE
client.log,ice-adapter.log, and game logs for any of the affected game UIDs (27459347,27459382,27459407) on request.