the symptom, in your words

"Dedicated server with an unpublished package — clients can't join"

✓ verified on engine 26.07lane: Writing gameplayposted

▸ SYMPTOM

A headless sbox-server.exe running a local (unpublished) .sbproj boots cleanly and creates a discoverable Steam lobby. But every client that tries to join — whether via in-play-mode Networking.Connect(lobbyId) from the same project's editor, or via a retail sbox.exe +connect <lobbyId> boot join — fails immediately with Package local.<ident> wasn't found! followed by GameInstance load failed, before any spawning occurs. The discovery and socket connect succeed; the failure is package resolution.

▸ CAUSE

The join handshake includes a ServerInfo.IsDeveloperHost flag, copied from NetworkSystem.IsDeveloperHost, whose only assignment is Application.IsEditor — which is always false in the dedicated-server binary. Clients grant themselves GameLoadingFlags.Developer (which tolerates a missing package and streams assemblies from the host) only when the host advertises dev-host = true — i.e., only when an editor hosts.

Without the developer flag, GameInstance.LoadAsync requires Package.FetchAsync(ident) to resolve the package ident on the sbox.game backend, which has no knowledge of a local.* identifier that was never published.

The documentation phrase "clients stream missing code from the server" is true for editor hosts, and for dedicated servers it works only as an overlay on a cloud-resolvable package ("assets are still fetched from the cloud version of the game").

▸ FIX

A true headless dedicated server requires publishing the package on sbox.game so joiners can resolve the ident. An unlisted or dev-visibility publish is sufficient — it does not need to be public.

Until published, local multiplayer testing must use an editor host. The -joinlocal mechanism is designed for this: launch additional clients via sbox.exe -joinlocal +instanceid N -sw -720, which TCP-connects to the editor host's 127.0.0.1:55333 socket with a per-instance fake SteamId.

▸ WHY IT WORKS

The dedicated-server binary is not the editor, so Application.IsEditor is false and the dev-host flag is never set. The engine's join protocol branches on this flag: dev-host clients stream code from the host's network table; non-dev-host clients fetch the package from the cloud by ident. A local.* ident has no cloud entry, so the fetch fails. Publishing creates the cloud entry, making the ident resolvable regardless of which binary hosts.

Verified on engine 26.07 — seen in a real project.
s&box moves fast; an undated fix is a liability. Spot a stale detail?