babalae/better-genshin-impact · error · InvalidDataException

预期相对鼠标处理结果帧,实际为 {frame.PayloadType}。

Error message

预期相对鼠标处理结果帧,实际为 {frame.PayloadType}。

What it means

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.

Source

Thrown at BetterGenshinImpact/Service/Instance/InstanceIpcProtocol.cs:269

        RelativeMouseResult result,
        CancellationToken cancellationToken)
    {
        var payload = new byte[RelativeMouseResultLength];
        BinaryPrimitives.WriteUInt64LittleEndian(payload, result.LastSequence);
        payload[sizeof(ulong)] = result.Handled ? (byte)1 : (byte)0;

        await WriteFrameAsync(
            stream,
            InstanceIpcPayloadType.RelativeMouseResult,
            payload,
            cancellationToken).ConfigureAwait(false);
    }

    internal static RelativeMouseResult ReadRelativeMouseResult(InstanceIpcFrame frame)
    {
        if (frame.PayloadType != InstanceIpcPayloadType.RelativeMouseResult)
        {
            throw new InvalidDataException($"预期相对鼠标处理结果帧,实际为 {frame.PayloadType}。");
        }

        var span = frame.Payload.AsSpan();
        if (span.Length != RelativeMouseResultLength || span[sizeof(ulong)] > 1)
        {
            throw new InvalidDataException("相对鼠标处理结果帧无效。");
        }

        return new RelativeMouseResult(
            BinaryPrimitives.ReadUInt64LittleEndian(span),
            span[sizeof(ulong)] == 1);
    }

    internal static async ValueTask<InstanceIpcFrame?> ReadFrameAsync(
        Stream stream,
        CancellationToken cancellationToken)
    {
        var header = new byte[FrameHeaderLength];

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Ensure both Primary and ChildSession processes run the same build/version of the IPC protocol so frame dispatch ordering matches.
  2. Inspect the InstanceConnection.ReceiveLoopAsync frame dispatch logic to confirm RelativeMouseResult frames are only routed to ReadRelativeMouseResult and never confused with JSON or batch frames.
  3. Catch InvalidDataException in the receive loop and close the connection so RootConnectionLoopAsync / AcceptLoopAsync can re-establish a clean session.
  4. Add diagnostic logging of frame.PayloadType at the dispatch point to identify which frame type is arriving unexpectedly.
Defensive patterns

Strategy: try-catch

Type guard

// Before calling ReadRelativeMouseResult, verify frame type
static bool IsRelativeMouseResultFrame(InstanceIpcFrame frame)
    => frame.PayloadType == InstanceIpcPayloadType.RelativeMouseResult;

Try / catch

try
{
    var result = InstanceIpcProtocol.ReadRelativeMouseResult(frame);
}
catch (InvalidDataException ex)
{
    _logger.LogError(ex, "帧类型不匹配:期望 RelativeMouseResult,实际 {Type}", frame.PayloadType);
    await connection.DisposeAsync();
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


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