mgth/LittleBigMouse · error · IOException
Malformed MQTT remaining length.
Error message
Malformed MQTT remaining length.
What it means
Thrown in ReadPacketAsync while decoding the MQTT variable-length remaining-length header: if the continuation loop runs past the maximum four bytes (multiplier exceeds 128^4), the framing is corrupt and the library throws IOException. This indicates a desynchronized stream — the client is no longer reading where packets begin, or the peer sent garbage.
Solutions
- Treat the connection as unrecoverable: close it and reopen with OpenMqttAsync — MQTT framing cannot resync mid-packet.
- Check that only one reader consumes the stream concurrently (double readers desynchronize framing).
- Verify TLS/certificate setup is correct — a mis-decrypted stream produces garbage bytes that break length decoding.
- Log the raw bytes before the failure to identify whether the peer or the client state caused the desync.
Example fix
// before: retry reads on the same broken stream
var packet = await ReadPacketAsync(stream, token);
// after: any framing error means reconnect
try { var packet = await ReadPacketAsync(stream, token); }
catch (IOException e) when (e.Message.Contains("Malformed MQTT remaining length"))
{ await CloseAsync(); await OpenMqttAsync(token); } Defensive patterns
Strategy: fallback
Validate before calling
// Only one reader should own the stream; assert before reading
if (readerRunning) throw new InvalidOperationException("A packet reader is already active on this MQTT stream."); Type guard
static bool IsFinalLengthByte(byte encoded) => (encoded & 128) == 0;
Try / catch
try { var packet = await ReadPacketAsync(stream, token); }
catch (IOException e) when (e.Message.Contains("Malformed MQTT remaining length"))
{ await CloseAsync(); await OpenMqttAsync(token); // framing cannot resync: full reconnect } Prevention
- Never allow concurrent readers on the same MQTT stream
- Reconnect on any framing error — mid-packet resync is impossible
- Validate TLS certificates so a bad decryption path can't feed garbage bytes
- Log raw bytes preceding the failure to distinguish peer corruption from client bugs
When it happens
Trigger: ReadPacketAsync (driven by ConnectAsync and the packet reader loop) reads remaining-length bytes whose continuation bit keeps being set beyond four encoded bytes — corrupt TCP stream, resync after a dropped/torn connection, or a peer sending non-MQTT bytes.
Common situations: Network middleboxes or flaky Wi-Fi corrupting/truncating the TLS stream; reading from a stale socket after the TV dropped the connection; connecting to a port that speaks a different protocol; a buffer/offset bug upstream leaving partial bytes in the stream.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- VIDAA returned an invalid MQTT connection response.
- MqttError(connack.Payload[1])
- The VIDAA MQTT connection is closed.
- VIDAA closed the MQTT connection.
- Enter a platform action name containing only letters…
AI-assisted analysis of mgth/LittleBigMouse@7a42f01d47 (2026-09-16).
Data as JSON: /api/errors/f71742a94e44b025.
Report an issue: GitHub.
Appendix: source
Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaMqttConnection.cs:248
body.CopyTo(packet);
return packet.ToArray();
}
static async Task<(byte Header, byte[] Payload)> ReadPacketAsync(
Stream stream,
CancellationToken cancellationToken)
{
var header = await ReadByteAsync(stream, cancellationToken).ConfigureAwait(false);
var multiplier = 1;
var length = 0;
byte encoded;
do
{
encoded = await ReadByteAsync(stream, cancellationToken).ConfigureAwait(false);
length += (encoded & 127) * multiplier;
multiplier *= 128;
if (multiplier > 128 * 128 * 128 * 128)
throw new IOException("Malformed MQTT remaining length.");
} while ((encoded & 128) != 0);
var payload = new byte[length];
await stream.ReadExactlyAsync(payload, cancellationToken).ConfigureAwait(false);
return (header, payload);
}
static async Task<byte> ReadByteAsync(Stream stream, CancellationToken cancellationToken)
{
var buffer = new byte[1];
if (await stream.ReadAsync(buffer, cancellationToken).ConfigureAwait(false) != 1)
throw new EndOfStreamException("VIDAA closed the MQTT connection.");
return buffer[0];
}
static void WriteUtf8(Stream stream, string value)
{
var bytes = Encoding.UTF8.GetBytes(value);View on GitHub (pinned to 7a42f01d47)