OpenRA/OpenRA · critical · InvalidDataException
Received packet from disconnected client '{clientId}'
Error message
Received packet from disconnected client '{clientId}' What it means
Thrown by OrderManager.ReceiveOrders when an order packet arrives from a clientId that has no entry in the pendingOrders dictionary. Each connected client is registered in pendingOrders; a packet from an unknown id means the client was never registered (or was already removed as disconnected), so the packet cannot be queued and is treated as a protocol error.
Source
Thrown at OpenRA.Game/Network/OrderManager.cs:194
public void ReceiveImmediateOrders(int clientId, OrderPacket orders)
{
foreach (var o in orders.GetOrders(World))
{
UnitOrders.ProcessOrder(this, World, clientId, o);
// A mod switch or other event has pulled the ground from beneath us
if (disposed)
return;
}
}
public void ReceiveOrders(int clientId, (int Frame, OrderPacket Orders) orders)
{
if (pendingOrders.TryGetValue(clientId, out var queue))
queue.Enqueue((orders.Frame, orders.Orders));
else
throw new InvalidDataException($"Received packet from disconnected client '{clientId}'");
}
void ReceiveAllOrdersAndCheckSync()
{
Connection.Receive(this);
}
bool IsReadyForNextFrame => GameStarted && pendingOrders.All(p => p.Value.Count > 0);
public int SuggestedTimestep
{
get
{
if (World == null)
return Ui.Timestep;
if (World.IsLoadingGameSave)
return 1;View on GitHub (pinned to a520984d91)
Solutions
- If you maintain custom networking, ensure packets for a clientId are only dispatched while that client is registered in pendingOrders (guard with a ContainsKey check before calling ReceiveOrders).
- For end users, this usually indicates a transient desync/disconnect; restarting the match typically resolves it.
- If persistent across all games, verify all peers run the same engine version.
Example fix
// caller guard before dispatching a packet to OrderManager
// before
orderManager.ReceiveOrders(o.ClientId, orders);
// after
if (pendingClientIds.Contains(o.ClientId))
orderManager.ReceiveOrders(o.ClientId, orders); Defensive patterns
Strategy: validation
Validate before calling
// Guard dispatch: only forward packets for registered clients
if (orderManager.PendingClientIds.Contains(o.ClientId))
orderManager.ReceiveOrders(o.ClientId, orders);
else
Log.Write("network", $"Dropping packet for unregistered client {o.ClientId}"); Try / catch
try { orderManager.ReceiveOrders(clientId, orders); }
catch (InvalidDataException ex) when (ex.Message.Contains("disconnected client"))
{ /* tolerate stray late packets from a just-disconnected client */ } Prevention
- Register every client in pendingOrders before dispatching its first packet.
- Drop, don't throw, for packets arriving shortly after a known disconnect (grace period).
- Keep custom networking code's client-lifecycle state in sync with the OrderManager.
When it happens
Trigger: ReceiveOrders(clientId, orders) is called where pendingOrders does not contain clientId — e.g. the client disconnected and was removed from pendingOrders, but a stray/late packet still arrives; or a server relayed a packet for an id the local client never saw register.
Common situations: A client disconnects and a final in-flight packet is processed after removal; network/server logic forwarding packets for a clientId outside the expected range; a reconnect or mod-switch state transition leaving pendingOrders inconsistent with the connection.
Related errors
- Received Ack for {ackCount} > {sentOrders.Count} frames.
- Attempted to process orders from client {clientId} for frame
- Received unknown packet from client {p.FromClient} with leng
- Handshake protocol version mismatch. Server={handshakeProtoc
- Invalid PEM public key
AI-assisted analysis of OpenRA/OpenRA@a520984d91 (2026-08-13).
Data as JSON: /api/errors/b67f0182a865a98e.
Report an issue: GitHub.