babalae/better-genshin-impact · warning · InvalidOperationException

WebView 不能向其他 WebView 发送消息。

Error message

WebView 不能向其他 WebView 发送消息。

What it means

Thrown by SendWebViewMessageAsync when Context.InstanceType == BetterGiInstanceType.WebView. The IPC topology is star-shaped: only Primary and ChildSession instances can originate WebView messages (Primary sends directly, ChildSession routes through Primary). A WebView instance is a leaf node that receives messages but cannot send to other WebViews or originate messages.

Source

Thrown at BetterGenshinImpact/Service/Instance/InstanceService.cs:205

        EnsureSuccessfulResponse(response);
        return response.Data?.ToObject<WebViewListResponse>(InstanceIpcProtocol.Serializer)
                   ?.Endpoints
               ?? [];
    }

    public async Task SendWebViewMessageAsync(
        int targetProcessId,
        string operation,
        JToken? data = null,
        CancellationToken cancellationToken = default)
    {
        if (string.IsNullOrWhiteSpace(operation))
        {
            throw new ArgumentException("WebView 操作名称不能为空。", nameof(operation));
        }
        if (Context.InstanceType == BetterGiInstanceType.WebView)
        {
            throw new InvalidOperationException("WebView 不能向其他 WebView 发送消息。");
        }

        if (Context.InstanceType == BetterGiInstanceType.Primary)
        {
            if (!_messageState.WebViewConnectionsByProcessId.TryGetValue(
                    targetProcessId,
                    out var target))
            {
                throw new InvalidOperationException(
                    $"WebView 进程 {targetProcessId} 当前不在线。");
            }

            var targetResponse = await target.Connection.SendRequestAsync(
                InstanceOperations.WebViewMessage,
                new WebViewMessage
                {
                    SourceProcessId = Context.ProcessId,
                    Operation = operation,

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Guard the call site with a check on Context.InstanceType before invoking SendWebViewMessageAsync.
  2. Verify the process was launched with the correct instance type — check command-line arguments and InstanceBootstrap.Initialize logic that determines the requested type.
  3. If the WebView needs to communicate back to Primary, use a different mechanism (e.g., the response to an incoming WebViewMessage request, not an outbound SendWebViewMessageAsync).

Example fix

// before
await instanceService.SendWebViewMessageAsync(targetPid, operation, data);

// after
if (instanceService.Context.InstanceType == BetterGiInstanceType.WebView)
{
    _logger.LogWarning("WebView 实例不能发送 WebView 消息,已跳过:{Operation}", operation);
    return;
}
await instanceService.SendWebViewMessageAsync(targetPid, operation, data);
Defensive patterns

Strategy: validation

Validate before calling

// Check instance type before calling
if (instanceService.Context.InstanceType != BetterGiInstanceType.WebView)
{
    await instanceService.SendWebViewMessageAsync(pid, operation, data);
}

Type guard

// Type guard for send-capable instances
static bool CanSendWebViewMessages(BetterGiInstanceType type)
    => type != BetterGiInstanceType.WebView;

Prevention

When it happens

Trigger: Code running inside a WebView-type BetterGI process calls SendWebViewMessageAsync. The WebView instance type is assigned by the root during connection.open when the process boots as a WebView helper. This is an architectural constraint enforced at the API boundary.

Common situations: A code path shared between Primary and WebView instances that unconditionally calls SendWebViewMessageAsync without checking the instance type; a misconfigured launch that started as WebView when it should have been Primary or ChildSession; test code running against a WebView-mode instance.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/32104e5fcf9dccef. Report an issue: GitHub.