{"record":{"id":"7cf85d9e8431da4d","repo":"egametang/ET","slug":"routermanager-dynamic-http-bind-failed-after-10-at","errorCode":null,"errorMessage":"RouterManager dynamic http bind failed after 10 attempts.","messagePattern":"RouterManager dynamic http bind failed after 10 attempts\\.","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"critical","filePath":"Packages/cn.etetet.router/Scripts/Hotfix/Server/FiberInit_RouterManager.cs","lineNumber":71,"sourceCode":"\n            Exception lastException = null;\n            for (int i = 0; i < 10; ++i)\n            {\n                int port = NetworkHelper.GetFreeTcpPort();\n                try\n                {\n                    root.AddComponent<HttpComponent, string>($\"http://{httpHost}:{port}/\");\n                    return port;\n                }\n                catch (Exception e)\n                {\n                    lastException = e;\n                    root.RemoveComponent<HttpComponent>();\n                    Log.Warning($\"router manager dynamic bind failed, port: {port}, attempt: {i + 1}\");\n                }\n            }\n\n            throw new Exception(\"RouterManager dynamic http bind failed after 10 attempts.\", lastException);\n        }\n    }\n}\n","sourceCodeStart":53,"sourceCodeEnd":75,"githubUrl":"https://github.com/egametang/ET/blob/5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f/Packages/cn.etetet.router/Scripts/Hotfix/Server/FiberInit_RouterManager.cs#L53-L75","documentation":"In test-scene mode, FiberInit_RouterManager.AddHttpComponent tries up to 10 random free TCP ports to bind an HttpComponent; on each failure it removes the component, logs a warning, and keeps the last exception. After 10 failures it throws with the inner exception attached.","triggerScenarios":"Options.Instance.SceneName equals the Test scene name, so the dynamic-bind loop runs. All 10 attempts to AddComponent<HttpComponent> on a NetworkHelper.GetFreeTcpPort() port throw (the port is freed but HttpComponent bind still fails). The final throw propagates the last inner exception.","commonSituations":"Exhaustion of ephemeral ports on the host; the 'free' port gets taken between GetFreeTcpPort and HttpComponent bind (TOCTOU race); HttpComponent bind failing for non-port reasons (permissions, IPv6/IPv4 mismatch with '+'/'*' host, certificate/config issue); many test scenes starting concurrently competing for ports; firewall blocking the range.","solutions":["Inspect lastException (logged via the inner exception) — if it's a socket bind error, address the root cause (permissions, address family, firewall).","Reduce concurrency of test scene startups so ports don't collide; add backoff between attempts.","Ensure the user has permission to bind the chosen ports and the host isn't port-exhausted (check netstat / TIME_WAIT).","Verify RuntimeInformation host string ('+' on Windows, '*' elsewhere) is valid for the HttpListener in use.","If running in a container/CI, confirm the expected port range is exposed/available."],"exampleFix":"// before: 10 rapid retries, TOCTOU-prone\nfor (int i = 0; i < 10; ++i) {\n    int port = NetworkHelper.GetFreeTcpPort();\n    root.AddComponent<HttpComponent, string>($\"http://{httpHost}:{port}/\");\n}\n// after: surface the real error and add delay\nthrow new Exception($\"RouterManager bind failed after 10 attempts. Last: {lastException}\", lastException);","handlingStrategy":"retry","validationCode":"// Pre-check that ports are likely available\nint available = NetworkHelper.GetFreeTcpPort();\nif (available == 0) {\n    throw new InvalidOperationException(\"No free TCP port available for RouterManager HTTP bind\");\n}","typeGuard":null,"tryCatchPattern":"try { /* AddHttpComponent loop already retries internally */ }\ncatch (Exception e) when (e.Message.Contains(\"RouterManager dynamic http bind failed\")) {\n    Log.Error($\"RouterManager bind failed after retries. Inner: {e.InnerException}\");\n    // inspect e.InnerException for the real socket error; fix root cause (permissions/firewall/exhaustion)\n    throw;\n}","preventionTips":["Inspect the inner exception — it carries the real bind failure reason.","Stagger test-scene startups to avoid port races.","Verify bind permissions and address-family validity of '+'/'*' host on the target OS.","Check for port exhaustion (TIME_WAIT) on hosts running many test scenes."],"tags":["router","network","http","port-binding","test-scene","race-condition"],"backgroundTag":null,"analyzedSha":"5cab01f7a8bee5f49f4781eebe9e2b1c6d7ebe0f","analyzedAt":"2026-08-13T21:10:40.377Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}