{"record":{"id":"2c8d83fed9336b15","repo":"mgth/LittleBigMouse","slug":"pair-this-hisense-vidaa-device-first","errorCode":null,"errorMessage":"Pair this Hisense VIDAA device first.","messagePattern":"Pair this Hisense VIDAA device first\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaSession.cs","lineNumber":52,"sourceCode":"        IReadOnlyList<string> topics,\n        CancellationToken cancellationToken)\n    {\n        await CloseAsync().ConfigureAwait(false);\n        var connection = await _transport(\n                VidaaConnectionProfile.Request(configuration, credentials), cancellationToken)\n            .ConfigureAwait(false);\n        connection.MessageReceived += Dispatch;\n        _connection = connection;\n        await connection.SubscribeAsync(topics, cancellationToken).ConfigureAwait(false);\n    }\n\n    /// <summary>Opens the session the stored pairing describes, unless one is already open.</summary>\n    /// <exception cref=\"InvalidOperationException\">The device has never been paired.</exception>\n    public async Task EnsureOpenAsync(CancellationToken cancellationToken)\n    {\n        if (Connected) return;\n        if (!configuration.HasPairing)\n            throw new InvalidOperationException(\"Pair this Hisense VIDAA device first.\");\n\n        await OpenAsync(\n            VidaaConnectionProfile.StoredCredentials(configuration),\n            VidaaConnectionProfile.ResponseTopics(configuration),\n            cancellationToken).ConfigureAwait(false);\n    }\n\n    /// <summary>\n    /// Publishes on the paired session, opening it if needed and giving the command a second\n    /// chance when the write is what reveals the broker dropped the previous one. See\n    /// <see cref=\"StaleConnectionRetry\"/>; here a dead session has to be closed before the\n    /// stored pairing can open another.\n    /// </summary>\n    public async Task SendAsync(string topic, string payload, CancellationToken cancellationToken)\n    {\n        await EnsureOpenAsync(cancellationToken).ConfigureAwait(false);\n        await StaleConnectionRetry.SendAsync(\n            token => PublishAsync(topic, payload, token),","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/mgth/LittleBigMouse/blob/7a42f01d47d99d223b8ee33ba4019af82adf1c48/LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaSession.cs#L34-L70","documentation":"EnsureOpenAsync opens the MQTT session described by the stored pairing, but throws InvalidOperationException when the configuration contains no pairing at all — the device has never completed the pairing handshake, so there are no credentials/topics to open the session with. The XML docs declare this contract explicitly.","triggerScenarios":"Calling EnsureOpenAsync (directly or via SendAsync/ReopenAsync) on a VidaaSession whose configuration.HasPairing is false — i.e. before AuthenticateAsync/pairing ever succeeded or after pairing data was cleared.","commonSituations":"Fresh install pointing at a device that was never paired; pairing data wiped (config reset, reinstalled app, device factory reset); trying to send keys/queries before running the pairing flow; tests exercising an unpaired session.","solutions":["Run the pairing flow first: open a pairing session, call AuthenticateAsync with the on-screen PIN, and let the access token be stored","Check configuration.HasPairing before attempting to use the session and route to the pairing UI otherwise","If the device was factory-reset, delete the stale config and re-pair","Restore/verify the stored pairing configuration file wasn't lost or emptied"],"exampleFix":"// before\nawait session.EnsureOpenAsync(ct);\nawait session.SendAsync(keyCmd, ct);\n// after\nif (!configuration.HasPairing)\n    await pairingUi.RunPairingAsync(ct); // stores the token\nawait session.EnsureOpenAsync(ct);","handlingStrategy":"validation","validationCode":"if (!configuration.HasPairing)\n{\n    ShowPairingUi(); // run AuthenticateAsync flow to obtain and store token\n    return;\n}\nawait session.EnsureOpenAsync(ct);","typeGuard":"bool IsPaired(VidaaConfiguration config) => config.HasPairing;","tryCatchPattern":null,"preventionTips":["Gate all session usage behind a HasPairing check that routes to the pairing UI","Re-pair automatically after device factory reset (stale pairing is rejected)","Persist pairing config reliably and verify it on startup","Never call SendAsync/ReopenAsync on a brand-new session before pairing"],"tags":["csharp","mqtt","pairing","hisense-vidaa","invalid-operation"],"backgroundTag":"authentication-required","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"}