{"record":{"id":"172b40eb2e97580c","repo":"babalae/better-genshin-impact","slug":"error-172b40","errorCode":null,"errorMessage":"相对鼠标处理结果帧无效。","messagePattern":"相对鼠标处理结果帧无效。","errorType":"exception","errorClass":"InvalidDataException","httpStatus":null,"severity":"error","filePath":"BetterGenshinImpact/Service/Instance/InstanceIpcProtocol.cs","lineNumber":275,"sourceCode":"\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];\n        var firstRead = await stream.ReadAsync(header.AsMemory(0, 1), cancellationToken).ConfigureAwait(false);\n        if (firstRead == 0)\n        {\n            return null;\n        }\n","sourceCodeStart":257,"sourceCodeEnd":293,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Service/Instance/InstanceIpcProtocol.cs#L257-L293","documentation":"Thrown by ReadRelativeMouseResult after the payload type check passes but the payload content is invalid. The result frame must be exactly RelativeMouseResultLength (9 bytes = sizeof(ulong) + sizeof(byte)) and the boolean byte at offset sizeof(ulong) must be 0 or 1. A wrong length or a boolean byte greater than 1 means the frame is structurally corrupt.","triggerScenarios":"A frame arrives with PayloadType == RelativeMouseResult but its payload is not exactly 9 bytes, or byte[8] (the Handled flag) is > 1. This can happen if the sender wrote a partial/truncated payload, if the stream was interrupted mid-write and the next read consumed stale bytes, or if the binary layout was changed in one peer but not the other.","commonSituations":"Named pipe connection dropped mid-write causing a short frame that gets concatenated with the next frame's header; a protocol version change that altered RelativeMouseResultLength without updating both peers; test code that hand-crafts a result frame with an incorrect payload size.","solutions":["Verify both peers use the same RelativeMouseResultLength constant (sizeof(ulong) + sizeof(byte) = 9) — any change must be deployed to all instances simultaneously.","Catch InvalidDataException in the receive loop and dispose the connection to force a clean reconnect via the accept/reconnect loops.","If writing test fixtures, ensure result frames are constructed via WriteRelativeMouseResultAsync rather than hand-encoding bytes.","Check for named pipe stream corruption — if this recurs, investigate whether a firewall, antivirus, or pipe proxy is altering the byte stream."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Validate frame structure before calling ReadRelativeMouseResult\nstatic bool IsValidRelativeMouseResultFrame(InstanceIpcFrame frame)\n{\n    var span = frame.Payload.AsSpan();\n    return span.Length == 9 && span[sizeof(ulong)] <= 1;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var result = InstanceIpcProtocol.ReadRelativeMouseResult(frame);\n}\ncatch (InvalidDataException)\n{\n    // Frame is corrupt — close connection to force resync\n    await connection.DisposeAsync();\n}","preventionTips":["Always construct result frames via WriteRelativeMouseResultAsync, never hand-encode bytes.","Keep RelativeMouseResultLength constant identical across all peers.","Tear down the connection on frame corruption rather than continuing with a misaligned stream."],"tags":["ipc","named-pipe","binary-protocol","frame-validation","relative-mouse"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}