{"record":{"id":"dfc6061d2914c364","repo":"stride3d/stride","slug":"cannot-listen-on-an-unusable-interface-check-the-isusable","errorCode":null,"errorMessage":"Cannot listen on an unusable interface. Check the IsUsable property before attemping to bind.","messagePattern":"Cannot listen on an unusable interface\\. Check the IsUsable property before attemping to bind\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Engine/Engine/Network/Sockets.Implementation.NET/TcpSocketListener.cs","lineNumber":57,"sourceCode":"        ///     Fired when a new TCP connection has been received.\n        ///     Use the <code>SocketClient</code> property of the <code>TcpSocketListenerConnectEventArgs</code>\n        ///     to get a <code>TcpSocketClient</code> representing the connection for sending and receiving data.\n        /// </summary>\n        public EventHandler<TcpSocketListenerConnectEventArgs> ConnectionReceived { get; set; }\n\n        /// <summary>\n        ///     Binds the <code>TcpSocketListener</code> to the specified port and listens for TCP connections.\n        /// </summary>\n        /// <param name=\"port\">The port to listen on.</param>\n        /// <param name=\"listenOn\">The <code>CommsInterface</code> to listen on. If unspecified, binds to the loopback interface.</param>\n        /// <param name=\"inheritHandle\">Allows handle inheritance. Might be ignored depending on platform.</param>\n        /// <returns></returns>\n        public Task StartListeningAsync(int port, ICommsInterface listenOn = null, bool inheritHandle = false)\n        {\n            return Task.Run(() =>\n            {\n                if (listenOn != null && !listenOn.IsUsable)\n                    throw new InvalidOperationException(\"Cannot listen on an unusable interface. Check the IsUsable property before attemping to bind.\");\n\n                var ipAddress = listenOn != null ? ((CommsInterface)listenOn).NativeIpAddress : IPAddress.Loopback;\n\n                _listenCanceller = new CancellationTokenSource();\n\n                _backingTcpListener = new TcpListener(ipAddress, port);\n                _backingTcpListener.Start();\n\n                if (Platform.Type == PlatformType.Windows && !inheritHandle)\n                    SetHandleInformation(_backingTcpListener.Server.Handle, HANDLE_FLAGS.Inherit, HANDLE_FLAGS.None);\n\n                WaitForConnections(_listenCanceller.Token);\n            });\n        }\n\n        /// <summary>\n        ///     Stops the <code>TcpSocketListener</code> from listening for new TCP connections.\n        ///     This does not disconnect existing connections.","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Engine/Engine/Network/Sockets.Implementation.NET/TcpSocketListener.cs#L39-L75","documentation":"TcpSocketListener.StartListeningAsync throws InvalidOperationException when asked to bind to an ICommsInterface whose IsUsable property is false. Stride requires callers to verify interface usability (e.g. interface is up, has an address) before binding a listener to it.","triggerScenarios":"Calling StartListeningAsync(port, listenOn) with a specific interface instance that is down, disconnected, or otherwise marked not usable.","commonSituations":"Binding to a WiFi interface that dropped; binding to a VPN/ethernet adapter that went offline; caching an ICommsInterface from startup and using it after the network changed.","solutions":["Check listenOn.IsUsable before calling StartListeningAsync and pick a usable interface","If listenOn is null it binds to IPAddress.Loopback; pass null or a usable interface instead","Re-enumerate NetworkInterface/comms interfaces at listen time instead of caching old ones","Handle the exception by falling back to loopback or another usable interface"],"exampleFix":"// before\nawait listener.StartListeningAsync(port, cachedInterface);\n// after\nif (cachedInterface.IsUsable)\n    await listener.StartListeningAsync(port, cachedInterface);\nelse\n    await listener.StartListeningAsync(port);","handlingStrategy":"validation","validationCode":"if (listenOn != null && !listenOn.IsUsable) listenOn = null; // fall back to loopback\nawait listener.StartListeningAsync(port, listenOn);","typeGuard":"bool CanBindOn(ICommsInterface i) => i == null || i.IsUsable;","tryCatchPattern":"try { await listener.StartListeningAsync(port, iface); }\ncatch (InvalidOperationException) { await listener.StartListeningAsync(port); }","preventionTips":["Always check IsUsable before binding to a specific interface","Re-enumerate interfaces at listen time instead of caching","Prefer null (loopback) for local-only servers","Wrap listen setup in try-catch with interface fallback"],"tags":["network","socket","tcp","binding"],"backgroundTag":"invalid-argument-value","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}