mgth/LittleBigMouse · error · IOException
VIDAA returned an invalid MQTT connection response.
Error message
VIDAA returned an invalid MQTT connection response.
What it means
Thrown in VidaaMqttConnection.ConnectAsync when the CONNACK packet returned by the Hisense VIDAA TV is not a valid MQTT connection acknowledgment: either the packet type (high nibble of the header) is not 2 (CONNACK) or the payload is shorter than 2 bytes. The library treats this as a protocol violation by the TV's MQTT broker rather than an authentication problem, so it surfaces as IOException. It means the device responded, but not with a recognizable MQTT handshake.
Solutions
- Verify the host and port point at the VIDAA TV's MQTT broker endpoint (not its HTTP API port).
- Power-cycle the TV and retry — a wedged broker can emit garbage instead of CONNACK.
- Confirm the TV model/firmware actually supports the VIDAA MQTT API this plugin targets; update or downgrade firmware if it changed the protocol.
- Capture traffic (or log the first bytes) on the socket to see what the TV actually returns before CONNACK is expected.
Example fix
// before: any exception bubbles up as-is
await connection.OpenMqttAsync(token);
// after: distinguish protocol failure from auth failure
try { await connection.OpenMqttAsync(token); }
catch (IOException e) when (e.Message.Contains("invalid MQTT connection response"))
{ /* wrong port/device or non-MQTT endpoint; fix host/port and retry */ } Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the endpoint speaks MQTT-TLS before connecting canConnect = Uri.TryCreate(tvHost, UriKind.Absolute, out var uri) && uri.Port == mqttTlsPort;
Type guard
bool IsValidConnack(byte header, byte[] payload) => (header >> 4) == 2 && payload.Length >= 2;
Try / catch
try { await connection.OpenMqttAsync(token); }
catch (IOException e) when (e.Message.Contains("invalid MQTT connection response"))
{ // endpoint is not answering MQTT: fix host/port or firmware before retrying } Prevention
- Confirm the port used is the VIDAA MQTT broker, not the TV's HTTP API
- Pin/verify TV model and firmware support before shipping the integration
- Power-cycle and re-check the TV after firmware updates
- Log raw first bytes on handshake failure to diagnose protocol mismatch
When it happens
Trigger: ConnectAsync (called via OpenMqttAsync) reads the first packet after connecting to the TV's MQTT-over-TLS port; if ((connack.Header >> 4) != 2 || connack.Payload.Length < 2) the IOException is thrown — e.g. the TV replied with a plain-HTTP error page, an MQTT PUBACK instead of CONNACK, or a truncated/empty CONNACK.
Common situations: Wrong target port on the TV (connecting to an HTTP endpoint instead of the MQTT broker), a non-VIDAA device or non-standard firmware on that port, a proxy/middlebox mangling the TLS stream, or an incompatible VIDAA firmware version that returns a non-standard handshake response.
Related errors
- Malformed MQTT remaining length.
- VIDAA closed the MQTT connection.
- MqttError(connack.Payload[1])
- The VIDAA MQTT connection is closed.
- No VIDAA descriptor answered at
AI-assisted analysis of mgth/LittleBigMouse@7a42f01d47 (2026-09-16).
Data as JSON: /api/errors/1f3bfce3f7388ff9.
Report an issue: GitHub.
Appendix: source
Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaMqttConnection.cs:86
{
throw new AuthenticationException(
"VIDAA rejected TLS. Select the PKCS#12 client certificate extracted from the official app.", e);
}
_stream = ssl;
await WritePacketAsync(BuildConnectPacket(clientId, username, password), cancellationToken)
.ConfigureAwait(false);
(byte Header, byte[] Payload) connack;
try
{
connack = await ReadPacketAsync(_stream, cancellationToken).ConfigureAwait(false);
}
catch (IOException e) when (certificates.Count == 0)
{
throw VidaaCertificate.MissingException(e);
}
if ((connack.Header >> 4) != 2 || connack.Payload.Length < 2)
throw new IOException("VIDAA returned an invalid MQTT connection response.");
if (connack.Payload[1] != 0)
throw new UnauthorizedAccessException(MqttError(connack.Payload[1]));
_connected = true;
// The caller token limits the handshake only. Once established, MQTT has
// its own lifetime so a completed UI command cannot tear down the session.
_lifetime = new CancellationTokenSource();
_readerTask = ReadLoopAsync(_lifetime.Token);
_pingTask = PingLoopAsync(_lifetime.Token);
}
public async Task SubscribeAsync(IEnumerable<string> topics, CancellationToken cancellationToken)
{
foreach (var topic in topics)
{
var id = unchecked(++_packetId);
if (id == 0) id = unchecked(++_packetId);
using var body = new MemoryStream();View on GitHub (pinned to 7a42f01d47)