{"record":{"id":"a1d1ddd8e0bdd075","repo":"mgth/LittleBigMouse","slug":"the-vidaa-connection-is-not-open","errorCode":null,"errorMessage":"The VIDAA connection is not open.","messagePattern":"The VIDAA connection is not open\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaPairing.cs","lineNumber":51,"sourceCode":"    public async Task StartAsync(bool requestPin, CancellationToken cancellationToken)\n    {\n        if (string.IsNullOrWhiteSpace(configuration.ControllerMacAddress))\n            configuration.ControllerMacAddress = NetworkIdentity.ControllerMacFor(configuration.IpAddress);\n\n        if (HisenseVidaaProtocol.UsesStaticLegacyProtocol(configuration.ProtocolVersion))\n            await StartLegacyAsync(requestPin, cancellationToken).ConfigureAwait(false);\n        else\n            await StartDynamicAsync(requestPin, cancellationToken).ConfigureAwait(false);\n    }\n\n    /// <summary>\n    /// Sends the PIN the device displays. On RemoteNOW that is the whole pairing; newer devices\n    /// answer it with an access token, which the router stores as it arrives.\n    /// </summary>\n    public async Task AuthenticateAsync(string pin, CancellationToken cancellationToken)\n    {\n        if (!session.Connected)\n            throw new InvalidOperationException(\"The VIDAA connection is not open.\");\n\n        var legacy = HisenseVidaaProtocol.UsesStaticLegacyProtocol(configuration.ProtocolVersion);\n        var pinAccepted = responses.PinAccepted.Expect();\n        var tokenIssued = responses.TokenIssued.Expect();\n        await session.PublishAsync(\n            HisenseVidaaProtocol.Topic(\"ui_service\", configuration.ClientId, \"authenticationcode\"),\n            legacy ? HisenseVidaaProtocol.LegacyPinPayload(pin) : HisenseVidaaProtocol.PinPayload(pin),\n            cancellationToken).ConfigureAwait(false);\n\n        await pinAccepted.WaitAsync(AnswerTimeout, cancellationToken).ConfigureAwait(false);\n        if (legacy)\n        {\n            configuration.LegacyAuthorized = true;\n            return;\n        }\n\n        await session.PublishAsync(\n            HisenseVidaaProtocol.TokenRequestTopic(configuration.ClientId),","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/mgth/LittleBigMouse/blob/7a42f01d47d99d223b8ee33ba4019af82adf1c48/LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaPairing.cs#L33-L69","documentation":"AuthenticateAsync sends the PIN to the Hisense VIDAA device over an MQTT session. It throws InvalidOperationException because the underlying session is not connected — pairing cannot proceed on a closed connection. The library guards up front rather than letting the publish fail obscurely mid-handshake.","triggerScenarios":"Calling AuthenticateAsync(pin) before VidaaSession.EnsureOpenAsync/OpenAsync has established the MQTT connection, or after the connection dropped (device rebooted, network loss, session closed by another code path).","commonSituations":"App skips the EnsureOpenAsync step and goes straight to PIN entry; device disconnected while user was typing the on-screen PIN; a previous authentication failure closed the session; connection lost due to projector standby.","solutions":["Call session.EnsureOpenAsync(ct) (or check session.Connected) before calling AuthenticateAsync","Await the EnsureOpenAsync/OpenAsync task and propagate its exceptions before the PIN flow","Re-open the session and retry AuthenticateAsync once if the connection dropped mid-flow","Check network/reachability of the projector if Connected stays false"],"exampleFix":"// before\nawait pairing.AuthenticateAsync(pin, ct);\n// after\nawait session.EnsureOpenAsync(ct);\nawait pairing.AuthenticateAsync(pin, ct);","handlingStrategy":"try-catch","validationCode":"if (!session.Connected)\n    await session.EnsureOpenAsync(ct);\nawait pairing.AuthenticateAsync(pin, ct);","typeGuard":"bool CanAuthenticate(IVidaaSession session) => session.Connected;","tryCatchPattern":"try\n{\n    await pairing.AuthenticateAsync(pin, ct);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"VIDAA connection is not open\"))\n{\n    await session.EnsureOpenAsync(ct);\n    await pairing.AuthenticateAsync(pin, ct); // retry once\n}","preventionTips":["Always await EnsureOpenAsync before any pairing call","Check session.Connected immediately before AuthenticateAsync","Handle device standby/network loss with a reconnect-and-retry wrapper","Never cache the session across long user interactions (e.g. PIN entry) without rechecking state"],"tags":["csharp","mqtt","invalid-operation","connection-state"],"backgroundTag":"invalid-state-transition","analyzedSha":"7a42f01d47d99d223b8ee33ba4019af82adf1c48","analyzedAt":"2026-09-16T00:35:00.514Z","contentChangedAt":"2026-09-16T00:35:00.514Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}