egametang/ET · critical · Exception
RouterManager dynamic http bind failed after 10 attempts.
Error message
RouterManager dynamic http bind failed after 10 attempts.
What it means
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.
Source
Thrown at Packages/cn.etetet.router/Scripts/Hotfix/Server/FiberInit_RouterManager.cs:71
Exception lastException = null;
for (int i = 0; i < 10; ++i)
{
int port = NetworkHelper.GetFreeTcpPort();
try
{
root.AddComponent<HttpComponent, string>($"http://{httpHost}:{port}/");
return port;
}
catch (Exception e)
{
lastException = e;
root.RemoveComponent<HttpComponent>();
Log.Warning($"router manager dynamic bind failed, port: {port}, attempt: {i + 1}");
}
}
throw new Exception("RouterManager dynamic http bind failed after 10 attempts.", lastException);
}
}
}
View on GitHub (pinned to 5cab01f7a8)
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.
Example fix
// before: 10 rapid retries, TOCTOU-prone
for (int i = 0; i < 10; ++i) {
int port = NetworkHelper.GetFreeTcpPort();
root.AddComponent<HttpComponent, string>($"http://{httpHost}:{port}/");
}
// after: surface the real error and add delay
throw new Exception($"RouterManager bind failed after 10 attempts. Last: {lastException}", lastException); Defensive patterns
Strategy: retry
Validate before calling
// Pre-check that ports are likely available
int available = NetworkHelper.GetFreeTcpPort();
if (available == 0) {
throw new InvalidOperationException("No free TCP port available for RouterManager HTTP bind");
} Try / catch
try { /* AddHttpComponent loop already retries internally */ }
catch (Exception e) when (e.Message.Contains("RouterManager dynamic http bind failed")) {
Log.Error($"RouterManager bind failed after retries. Inner: {e.InnerException}");
// inspect e.InnerException for the real socket error; fix root cause (permissions/firewall/exhaustion)
throw;
} Prevention
- 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.
When it happens
Trigger: 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.
Common situations: 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.
Related errors
- 请先在cmd中运行: netsh http add urlacl url=http://*:你的address中的端口/
- http request fail: {link.Substring(0,link.IndexOf('?'))}\n{e
- http request fail: {link.Substring(0,link.IndexOf('?'))}\n{e
- get router fail: {netComponent.Root().Id} {address}
- Only IPv4 addresses are supported
AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13).
Data as JSON: /api/errors/7cf85d9e8431da4d.
Report an issue: GitHub.