babalae/better-genshin-impact · warning · ArgumentOutOfRangeException
timeout 必须大于 0
Error message
timeout 必须大于 0
What it means
Thrown by HtmlMaskWindow.Show when the count of already-open HTML mask windows reaches MaxWindows (5). HtmlMaskWindow manages a static ConcurrentDictionary of active overlay windows; exceeding the cap prevents resource exhaustion from too many WebView2 instances. The exception is InvalidOperationException thrown on the UI dispatcher thread.
Source
Thrown at BetterGenshinImpact/Core/BgiVision/BvLocator.cs:277
RetryAction = (results) =>
{
action(results);
return Task.CompletedTask;
};
}
return this;
}
/// <summary>
/// 设置超时时间(毫秒)
/// </summary>
/// <param name="timeout">超时时间(毫秒)</param>
/// <returns></returns>
public BvLocator WithTimeout(int timeout)
{
if (timeout <= 0)
{
throw new ArgumentOutOfRangeException(nameof(timeout), "timeout 必须大于 0");
}
_timeout = timeout;
return this;
}
/// <summary>
/// 设置重试间隔(毫秒)
/// </summary>
/// <param name="retryInterval">重试间隔(毫秒)</param>
/// <returns></returns>
public BvLocator WithRetryInterval(int retryInterval)
{
if (retryInterval <= 0)
{
throw new ArgumentOutOfRangeException(nameof(retryInterval), "retryInterval 必须大于 0");
}
_retryInterval = retryInterval;
return this;View on GitHub (pinned to a7cb36712d)
Solutions
- Close unneeded windows via HtmlMaskWindow.Close(id) or CloseAll() before opening new ones.
- Reuse existing window ids to replace rather than accumulate windows.
- Audit that the Closed event handler reliably removes entries from _windows (check for disposal/exception leaks).
- Catch InvalidOperationException in the caller and present a user message to close existing overlays.
Example fix
// before
if (_windows.Count >= MaxWindows)
throw new InvalidOperationException($"最多同时打开 {MaxWindows} 个HTML遮罩窗口");
// after — auto-close oldest window or return error id
if (_windows.Count >= MaxWindows)
{
var oldest = _windows.Values.OrderBy(w => w._createdAt).FirstOrDefault();
oldest?.Close();
}
if (_windows.Count >= MaxWindows)
return string.Empty; // caller checks for empty id
Defensive patterns
Strategy: validation
Validate before calling
// Check window count before opening
if (HtmlMaskWindow.ActiveCount >= 5)
{
HtmlMaskWindow.CloseAll(); // or close oldest
}
var id = HtmlMaskWindow.Show(url, myId, workDir); Type guard
static bool CanOpenNewWindow() => _windows.Count < MaxWindows;
Try / catch
try { return HtmlMaskWindow.Show(url, id, workDir); }
catch (InvalidOperationException ex) when (ex.Message.Contains("MaxWindows"))
{ HtmlMaskWindow.CloseAll(); return HtmlMaskWindow.Show(url, id, workDir); } Prevention
- Reuse existing window ids to replace rather than accumulate overlays.
- Close windows explicitly via Close(id) when done.
- Audit the Closed event handler to ensure _windows is pruned on every disposal.
When it happens
Trigger: HtmlMaskWindow.Show is called while _windows.Count >= 5. The per-id replacement logic (closing existing window with same id) runs first, so this triggers only when there are 5 windows with distinct ids and a new unique-id window is requested.
Common situations: A script opens multiple HTML overlays without closing previous ones, a bug leaks windows (Closed handler didn't fire so _windows wasn't pruned), or a script loops creating overlays without cleanup.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/26be95942ee73a61.
Report an issue: GitHub.