"QueryLobbies never finds your Hidden lobby"
▸ SYMPTOM
You build a "join by short code" flow: the host stamps a code onto a Hidden = true, Privacy = Public lobby with SetData, and the joiner runs Networking.QueryLobbies({ code }) to find it and connect. The engine docs say Hidden lobbies are "still queryable programmatically" — but the query returns zero lobbies, even for a real second peer pasting the code:
no server found for code WRLD-XXXXA single-client self-query (host querying its own just-created lobby) also comes back empty, even after a propagation wait.
▸ CAUSE
There are two independent reasons a Hidden lobby doesn't come back, and they stack.
1. The default query excludes hidden lobbies by construction. Networking.QueryLobbies appends a hidden = 0 (hdn:0) filter to the query unless you pass a truthy "hidden" key yourself. A Hidden = true (hdn = 1) lobby therefore fails the filter on every ordinary query — it is structurally excluded, not lost to propagation lag or self-membership. A metadata-code lookup on a Hidden lobby can never work for a real peer with the default filter.
2. The bool overload does not do what its name suggests. The second parameter of QueryLobbies(Dictionary, bool, ct) is includeServers (merge dedicated servers into the results), not hidden-inclusion. Passing true there does nothing for hidden lobbies.
3. Editor hosts force Private privacy. When Application.IsEditor is true, Networking.CreateLobbyAsync forces the lobby's Privacy to the editor default (LobbyPrivacy.Private). Steam excludes Private-type lobbies from every list query regardless of the hidden filter. So a self-query run in the editor is expected to return nothing and tells you nothing about how the published, public build behaves — the public path is only testable on a published build.
A single-peer self-query is a weak probe on top of all this: Steam commonly excludes lobbies the querying client is already a member of, so foundSelf:false is consistent with both "broken" and "works fine for a real second peer."
▸ FIX
To make a Hidden lobby findable by code, pass the hidden filter key explicitly:
var results = await Networking.QueryLobbies( new()
{
["code"] = code,
["hidden"] = "1", // engine special-cases "hidden"/"hdn" and skips the hdn:0 append
} );The engine special-cases the "hidden" / "hdn" key and, when it is truthy, does not append hdn:0, so hidden lobbies come back.
Verify on a genuine second Steam client on a published build — never conclude anything from a single-peer self-query, and never from the editor (where forced-Private privacy dominates). If you don't need the lobby hidden, the simplest robust path is to make it visible (Hidden = false) and keep the join code secret another way. As a fallback, encode the lobby id into the code and Networking.Connect(target) directly, skipping the query round-trip entirely.
▸ WHY IT WORKS
The default hdn:0 filter is the whole reason ordinary queries skip hidden lobbies; supplying a truthy "hidden" key suppresses that filter so the lobby is eligible again. Testing on a real second peer on a published build removes the two confounds that make editor and self-queries meaningless — forced-Private privacy and self-membership exclusion — so you're measuring the path players will actually take.
- Published