EllanJiang/GameFramework · error · GameFrameworkException

You must connect first.

Error message

You must connect first.

What it means

NetworkChannelBase.Send<T> checks that the channel's underlying Socket exists before enqueueing a packet. If m_Socket is null, the channel has never connected (or Dispose already ran), so GameFramework throws this GameFrameworkException (or fires NetworkChannelError with NetworkErrorCode.SendError if a handler is registered). It guards against sending on a channel with no socket.

Solutions

  1. Call channel.Connect(ipAddress, port, userData) and wait for the NetworkChannelConnected event before calling Send.
  2. Check the channel's state (or track connection success) before each Send; skip or queue packets while not connected.
  3. If the channel was disposed after a disconnect, create/reconnect a new channel via NetworkManager.CreateNetworkChannel instead of reusing the old one.
  4. Register NetworkChannelError to receive SendError as an event instead of an unhandled exception.

Example fix

// before
channel.Send(loginPacket); // throws if never connected
// after
channel.Connected += (sender, e) => channel.Send(loginPacket);
channel.Connect(ipAddress, port, userData);
Defensive patterns

Strategy: validation

Validate before calling

public static bool CanSend(INetworkChannel ch) => ch != null && ch.Id != 0 && IsConnected(ch); // track connection via NetworkChannelConnected/Closed events

Type guard

public static bool IsConnected(INetworkChannel ch) => connectedChannels.Contains(ch);

Try / catch

try { channel.Send(packet); } catch (GameFrameworkException ex) when (ex.Message == "You must connect first.") { QueueForLater(packet); }

Prevention

When it happens

Trigger: Calling Send<T> on an INetworkChannel obtained from networkManager.GetNetworkChannel/CreateNetworkChannel before ever calling Connect; calling Send after the channel was closed/Disposed (socket set to null); racing a send against channel disposal.

Common situations: Scripts that start sending in Unity Start/Awake before the async Connect completes or on a failed connection; sending after server disconnect handling disposed the channel; forgetting that each channel must be connected individually.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15). Data as JSON: /api/errors/29c9690bf26beddd. Report an issue: GitHub.

Appendix: source

Thrown at GameFramework/Network/NetworkManager.NetworkChannelBase.cs:430

            }

            /// <summary>
            /// 向远程主机发送消息包。
            /// </summary>
            /// <typeparam name="T">消息包类型。</typeparam>
            /// <param name="packet">要发送的消息包。</param>
            public void Send<T>(T packet) where T : Packet
            {
                if (m_Socket == null)
                {
                    string errorMessage = "You must connect first.";
                    if (NetworkChannelError != null)
                    {
                        NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage);
                        return;
                    }

                    throw new GameFrameworkException(errorMessage);
                }

                if (!m_Active)
                {
                    string errorMessage = "Socket is not active.";
                    if (NetworkChannelError != null)
                    {
                        NetworkChannelError(this, NetworkErrorCode.SendError, SocketError.Success, errorMessage);
                        return;
                    }

                    throw new GameFrameworkException(errorMessage);
                }

                if (packet == null)
                {
                    string errorMessage = "Packet is invalid.";
                    if (NetworkChannelError != null)

View on GitHub (pinned to d0c010b051)