{"record":{"id":"f267e96195bf2da6","repo":"babalae/better-genshin-impact","slug":"frame-payloadtype-f267e9","errorCode":null,"errorMessage":"预期相对鼠标处理结果帧，实际为 {frame.PayloadType}。","messagePattern":"预期相对鼠标处理结果帧，实际为 (.+?)。","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Service/Instance/InstanceIpcProtocol.cs","lineNumber":269,"sourceCode":"        RelativeMouseResult result,\n        CancellationToken cancellationToken)\n    {\n        var payload = new byte[RelativeMouseResultLength];\n        BinaryPrimitives.WriteUInt64LittleEndian(payload, result.LastSequence);\n        payload[sizeof(ulong)] = result.Handled ? (byte)1 : (byte)0;\n\n        await WriteFrameAsync(\n            stream,\n            InstanceIpcPayloadType.RelativeMouseResult,\n            payload,\n            cancellationToken).ConfigureAwait(false);\n    }\n\n    internal static RelativeMouseResult ReadRelativeMouseResult(InstanceIpcFrame frame)\n    {\n        if (frame.PayloadType != InstanceIpcPayloadType.RelativeMouseResult)\n        {\n            throw new InvalidDataException($\"预期相对鼠标处理结果帧，实际为 {frame.PayloadType}。\");\n        }\n\n        var span = frame.Payload.AsSpan();\n        if (span.Length != RelativeMouseResultLength || span[sizeof(ulong)] > 1)\n        {\n            throw new InvalidDataException(\"相对鼠标处理结果帧无效。\");\n        }\n\n        return new RelativeMouseResult(\n            BinaryPrimitives.ReadUInt64LittleEndian(span),\n            span[sizeof(ulong)] == 1);\n    }\n\n    internal static async ValueTask<InstanceIpcFrame?> ReadFrameAsync(\n        Stream stream,\n        CancellationToken cancellationToken)\n    {\n        var header = new byte[FrameHeaderLength];","sourceCodeStart":251,"sourceCodeEnd":287,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Service/Instance/InstanceIpcProtocol.cs#L251-L287","documentation":"Thrown by ReadRelativeMouseResult when the frame passed to it has a PayloadType that is not InstanceIpcPayloadType.RelativeMouseResult (value 3). The IPC framing layer (ReadFrameAsync) parses a 5-byte header containing a 4-byte length and a 1-byte payload type. ReadRelativeMouseResult expects only RelativeMouseResult frames; any other type (Utf8Json=1, RelativeMouseBatch=2) is a protocol desynchronization.","triggerScenarios":"The InstanceConnection receive loop dispatched a frame to ReadRelativeMouseResult that is actually a Utf8Json envelope or a RelativeMouseBatch. This indicates the frame-type dispatch logic in the receive loop is out of sync with what the peer sent — for example, the peer sent a JSON response but the local code path tried to read it as a mouse result frame. It can also occur if the pipe stream gets partially consumed or skipped, causing the next frame header to be misaligned.","commonSituations":"Protocol version mismatch between Primary and ChildSession where one side added a new frame type or changed the dispatch order; a bug in the receive loop that consumes the wrong number of bytes from the stream, shifting all subsequent frame boundaries; a race condition where a RelativeMouseResult reader is invoked after the connection already transitioned to JSON-only mode during shutdown.","solutions":["Ensure both Primary and ChildSession processes run the same build/version of the IPC protocol so frame dispatch ordering matches.","Inspect the InstanceConnection.ReceiveLoopAsync frame dispatch logic to confirm RelativeMouseResult frames are only routed to ReadRelativeMouseResult and never confused with JSON or batch frames.","Catch InvalidDataException in the receive loop and close the connection so RootConnectionLoopAsync / AcceptLoopAsync can re-establish a clean session.","Add diagnostic logging of frame.PayloadType at the dispatch point to identify which frame type is arriving unexpectedly."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":null,"typeGuard":"// Before calling ReadRelativeMouseResult, verify frame type\nstatic bool IsRelativeMouseResultFrame(InstanceIpcFrame frame)\n    => frame.PayloadType == InstanceIpcPayloadType.RelativeMouseResult;","tryCatchPattern":"try\n{\n    var result = InstanceIpcProtocol.ReadRelativeMouseResult(frame);\n}\ncatch (InvalidDataException ex)\n{\n    _logger.LogError(ex, \"帧类型不匹配：期望 RelativeMouseResult，实际 {Type}\", frame.PayloadType);\n    await connection.DisposeAsync();\n}","preventionTips":["Route frames to the correct reader based on PayloadType in the receive loop dispatch.","Ensure protocol version match so frame type expectations are aligned.","Log frame.PayloadType at every dispatch branch to catch desyncs early."],"tags":["ipc","named-pipe","binary-protocol","frame-desync","relative-mouse"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}