babalae/better-genshin-impact · error · InvalidOperationException
HTML遮罩窗口不存在或已关闭: {windowId}
Error message
HTML遮罩窗口不存在或已关闭: {windowId} What it means
Thrown by HtmlMask.Send when the specified windowId does not correspond to an existing HtmlMaskWindow or when the internal message queue for that windowId has been removed. This indicates the overlay window was never created (Show not called), has been closed by the user, or was disposed.
Source
Thrown at BetterGenshinImpact/Core/Script/Dependence/HtmlMask.cs:187
/// 切换窗口的点击穿透模式
/// </summary>
/// <param name="windowId">窗口ID</param>
public void ToggleClickThrough(string windowId)
{
HtmlMaskWindow.ToggleClickThrough(windowId);
}
#endregion
#region 消息通信
/// <summary>
/// 发送消息到HTML(单向推送)
/// </summary>
public void Send(string windowId, string url, string jsonData)
{
if (!HtmlMaskWindow.Exists(windowId) || !_toHtmlQueues.TryGetValue(windowId, out var queue))
throw new InvalidOperationException($"HTML遮罩窗口不存在或已关闭: {windowId}");
queue.Enqueue(new Message
{
Url = url,
Data = ParseData(jsonData)
});
HtmlMaskWindow.NotifyFlush(windowId);
}
/// <summary>
/// 响应 HTML 页面通过 window.htmlMask.request(...) 发起的请求。
/// </summary>
/// <param name="windowId">HTML 遮罩窗口 ID。</param>
/// <param name="requestId">从 Receive/Poll/PollAll 返回消息的 requestId 字段取得,不能由脚本自行生成。</param>
/// <param name="jsonData">响应数据,必须是合法 JSON 字符串。</param>
public void Respond(string windowId, string requestId, string jsonData)
{View on GitHub (pinned to a7cb36712d)
Solutions
- Call htmlMask.Exists(windowId) before Send/Respond/Request to verify the window is still open.
- Store the windowId returned by Show() and reuse it — do not hardcode or reconstruct it.
- Guard async background tasks: check Exists before each send, and cancel if the window is gone.
- Ensure Show() is called and awaited/completed before any Send/Respond/Request calls.
Example fix
// before
htmlMask.Send(windowId, "/update", jsonData);
// after
if (htmlMask.Exists(windowId))
{
htmlMask.Send(windowId, "/update", jsonData);
}
else
{
// re-create window or skip
_logger.LogWarning("Window {Id} no longer exists, skipping send", windowId);
} Defensive patterns
Strategy: validation
Validate before calling
// Check window existence before calling Send
if (!htmlMask.Exists(windowId))
{
_logger.LogWarning("Window {Id} does not exist or is closed", windowId);
return;
}
htmlMask.Send(windowId, url, jsonData); Try / catch
try
{
htmlMask.Send(windowId, url, jsonData);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("不存在或已关闭"))
{
_logger.LogWarning("Send failed: window {Id} closed", windowId);
} Prevention
- Always call htmlMask.Exists(windowId) before Send/Respond/Request.
- Store and reuse the exact windowId returned by Show().
- Cancel background tasks when the window is closed.
- Call Show() and wait for it to complete before any communication.
When it happens
Trigger: Calling htmlMask.Send(windowId, url, jsonData) before calling htmlMask.Show(url, windowId), or after the window was closed. Also triggered if the windowId was never registered or was misspelled.
Common situations: Script creates a window with Show(url, "myWindow") but then calls Send("mywindows", ...) with a typo. Window was closed by the user or auto-closed after script termination, but Send is still called from a background task. The HtmlMask instance was disposed.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/52ac9aa880104230.
Report an issue: GitHub.