{"record":{"id":"52ac9aa880104230","repo":"babalae/better-genshin-impact","slug":"html-windowid","errorCode":null,"errorMessage":"HTML遮罩窗口不存在或已关闭: {windowId}","messagePattern":"HTML遮罩窗口不存在或已关闭: (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Core/Script/Dependence/HtmlMask.cs","lineNumber":187,"sourceCode":"    /// 切换窗口的点击穿透模式\n    /// </summary>\n    /// <param name=\"windowId\">窗口ID</param>\n    public void ToggleClickThrough(string windowId)\n    {\n        HtmlMaskWindow.ToggleClickThrough(windowId);\n    }\n\n    #endregion\n\n    #region 消息通信\n\n    /// <summary>\n    /// 发送消息到HTML（单向推送）\n    /// </summary>\n    public void Send(string windowId, string url, string jsonData)\n    {\n        if (!HtmlMaskWindow.Exists(windowId) || !_toHtmlQueues.TryGetValue(windowId, out var queue))\n            throw new InvalidOperationException($\"HTML遮罩窗口不存在或已关闭: {windowId}\");\n\n        queue.Enqueue(new Message\n        {\n            Url = url,\n            Data = ParseData(jsonData)\n        });\n\n        HtmlMaskWindow.NotifyFlush(windowId);\n    }\n\n    /// <summary>\n    /// 响应 HTML 页面通过 window.htmlMask.request(...) 发起的请求。\n    /// </summary>\n    /// <param name=\"windowId\">HTML 遮罩窗口 ID。</param>\n    /// <param name=\"requestId\">从 Receive/Poll/PollAll 返回消息的 requestId 字段取得，不能由脚本自行生成。</param>\n    /// <param name=\"jsonData\">响应数据，必须是合法 JSON 字符串。</param>\n    public void Respond(string windowId, string requestId, string jsonData)\n    {","sourceCodeStart":169,"sourceCodeEnd":205,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/Script/Dependence/HtmlMask.cs#L169-L205","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"// before\nhtmlMask.Send(windowId, \"/update\", jsonData);\n\n// after\nif (htmlMask.Exists(windowId))\n{\n    htmlMask.Send(windowId, \"/update\", jsonData);\n}\nelse\n{\n    // re-create window or skip\n    _logger.LogWarning(\"Window {Id} no longer exists, skipping send\", windowId);\n}","handlingStrategy":"validation","validationCode":"// Check window existence before calling Send\nif (!htmlMask.Exists(windowId))\n{\n    _logger.LogWarning(\"Window {Id} does not exist or is closed\", windowId);\n    return;\n}\nhtmlMask.Send(windowId, url, jsonData);","typeGuard":null,"tryCatchPattern":"try\n{\n    htmlMask.Send(windowId, url, jsonData);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"不存在或已关闭\"))\n{\n    _logger.LogWarning(\"Send failed: window {Id} closed\", windowId);\n}","preventionTips":["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."],"tags":["html-mask","window-management","precondition","lifecycle"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}