{"record":{"id":"046d1980d4a08f0a","repo":"babalae/better-genshin-impact","slug":"error-046d19","errorCode":null,"errorMessage":"根实例连接在完成登记前已经关闭。","messagePattern":"根实例连接在完成登记前已经关闭。","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"warning","filePath":"BetterGenshinImpact/Service/Instance/InstanceService.cs","lineNumber":461,"sourceCode":"                    throw new InvalidOperationException(\n                        $\"根实例分配了不匹配的客户端类型：{openResponse.AssignedType}。\");\n                }\n\n                Context.SetRootSessionId(openResponse.RootSessionId);\n                connection.RemoteEndpoint = new InstanceEndpoint\n                {\n                    InstanceType = BetterGiInstanceType.Primary,\n                    ProcessId = openResponse.RootProcessId,\n                    WindowsSessionId = openResponse.RootSessionId,\n                    StartedAt = DateTimeOffset.UtcNow\n                };\n                if (!connection.IsStarted)\n                {\n                    connection.Start(cancellationToken);\n                }\n                if (connection.Completion.IsCompleted)\n                {\n                    throw new IOException(\"根实例连接在完成登记前已经关闭。\");\n                }\n\n                lock (_rootConnectionLock)\n                {\n                    _rootConnection = connection;\n                }\n\n                includeActivationArguments = false;\n                restartFromProcessId = null;\n                _logger.LogInformation(\n                    \"已连接 BetterGI 根实例：进程 {ProcessId}，Session {SessionId}\",\n                    openResponse.RootProcessId,\n                    openResponse.RootSessionId);\n\n                if (Context.InstanceType == BetterGiInstanceType.ChildSession)\n                {\n                    var subscribeResponse = await connection.SendRequestAsync(\n                        InstanceOperations.RelativeMouseSubscribe,","sourceCodeStart":443,"sourceCodeEnd":479,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Service/Instance/InstanceService.cs#L443-L479","documentation":"Thrown in RootConnectionLoopAsync when the root connection's Completion task is already completed immediately after sending the connection.open request and starting the connection. This means the pipe connection to the root broke in the narrow window between the open handshake response and the registration step (setting _rootConnection). An IOException is used (not InvalidDataException) because the root cause is a transport failure, not a protocol violation.","triggerScenarios":"After the child sends connection.open and receives a successful response, it calls connection.Start() (if not already started) and then checks connection.Completion.IsCompleted. If the receive loop already exited — because the root process exited, the pipe closed, or the CancellationToken fired — this fires. The window is extremely narrow: between receiving the open response and assigning _rootConnection.","commonSituations":"The root (Primary) process crashed or was killed immediately after responding to connection.open; the user shut down BetterGI while a child was connecting; a Windows session disconnect/logoff caused the pipe to close; a cancellation token from StopAsync fired during a reconnect cycle.","solutions":["This is handled gracefully by the catch block for IOException in RootConnectionLoopAsync — the loop will log a warning and retry after ReconnectDelay (1 second). Ensure that catch block is intact.","If the root is genuinely gone, the retry loop will keep failing — investigate why the root process exited (check Windows Event Log, BetterGI logs).","If this occurs during shutdown, ensure the lifetime CancellationToken is being cancelled cleanly and the catch for OperationCanceledException suppresses the warning.","Add logging of the Completion task's exception (if any) to diagnose why the receive loop terminated."],"exampleFix":null,"handlingStrategy":"retry","validationCode":null,"typeGuard":null,"tryCatchPattern":"// Already handled by RootConnectionLoopAsync's IOException catch:\ncatch (Exception exception) when (exception is IOException or UnauthorizedAccessException\n    or TimeoutException or OperationCanceledException or ObjectDisposedException)\n{\n    _logger.LogWarning(exception, \"连接根实例失败，稍后重试\");\n    // Loop continues, retries after ReconnectDelay\n}","preventionTips":["This is a transient transport failure — the reconnect loop handles it automatically.","Ensure the root process is running and stable.","Check Windows Event Log if the root keeps crashing during child connection."],"tags":["ipc","named-pipe","connection-lifecycle","race-condition","root-connection"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}