babalae/better-genshin-impact · error · InvalidDataException

相对鼠标帧头不完整。

Error message

相对鼠标帧头不完整。

What it means

Thrown by ReadRelativeMouseBatch when the payload is shorter than RelativeMouseBatchHeaderLength (14 bytes: ushort count + ulong firstSequence + long baseTicks). The header cannot be read, so the batch is unparseable.

Source

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

            BinaryPrimitives.WriteInt32LittleEndian(span[(offset + sizeof(int) * 2)..], offsetMicroseconds);
            offset += RelativeMouseSampleLength;
        }

        return payload;
    }

    internal static (ulong FirstSequence, RelativeMouseSample[] Samples) ReadRelativeMouseBatch(
        InstanceIpcFrame frame)
    {
        if (frame.PayloadType != InstanceIpcPayloadType.RelativeMouseBatch)
        {
            throw new InvalidDataException($"预期相对鼠标帧,实际为 {frame.PayloadType}。");
        }

        var span = frame.Payload.AsSpan();
        if (span.Length < RelativeMouseBatchHeaderLength)
        {
            throw new InvalidDataException("相对鼠标帧头不完整。");
        }

        var count = BinaryPrimitives.ReadUInt16LittleEndian(span);
        if (count is 0 or > 64
            || span.Length != RelativeMouseBatchHeaderLength + RelativeMouseSampleLength * count)
        {
            throw new InvalidDataException("相对鼠标帧长度无效。");
        }

        var firstSequence = BinaryPrimitives.ReadUInt64LittleEndian(span[sizeof(ushort)..]);
        var baseTicks = BinaryPrimitives.ReadInt64LittleEndian(span[(sizeof(ushort) + sizeof(ulong))..]);
        var samples = new RelativeMouseSample[count];
        var offset = RelativeMouseBatchHeaderLength;
        for (var index = 0; index < count; index++)
        {
            var deltaX = BinaryPrimitives.ReadInt32LittleEndian(span[offset..]);
            var deltaY = BinaryPrimitives.ReadInt32LittleEndian(span[(offset + sizeof(int))..]);
            var offsetMicroseconds =

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Restart both instances to re-establish the pipe.
  2. Ensure both instances run the same build (header layout must match).
  3. If reproducing, inspect the declared payload length vs the 14-byte header minimum — a peer-side length bug is likely.
Defensive patterns

Strategy: try-catch

Validate before calling

if (frame.Payload.Length < RelativeMouseBatchHeaderLength)
{
    throw new InvalidDataException("相对鼠标帧头不完整。");
}

Try / catch

try
{
    var (firstSeq, samples) = InstanceIpcProtocol.ReadRelativeMouseBatch(frame.Value);
}
catch (InvalidDataException ex) when (ex.Message.Contains("帧头不完整"))
{
    logger.LogError(ex, "Truncated mouse-batch header; restart instances");
}

Prevention

When it happens

Trigger: A truncated payload reached the reader: a partial pipe write, a premature connection close mid-frame, or a peer that sent an undersized buffer. Note the framing layer (ReadFrameAsync) reads exactly payloadLength bytes, so this implies the peer declared a length too small for a valid header.

Common situations: Peer bug computing payload length; connection drop between header and body; memory/encoding error on the writer side; version skew where the peer uses a smaller header layout.

Related errors


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