mgth/LittleBigMouse · error · InvalidOperationException

Pair this Hisense VIDAA device first.

Error message

Pair this Hisense VIDAA device first.

What it means

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.

Solutions

  1. Run the pairing flow first: open a pairing session, call AuthenticateAsync with the on-screen PIN, and let the access token be stored
  2. Check configuration.HasPairing before attempting to use the session and route to the pairing UI otherwise
  3. If the device was factory-reset, delete the stale config and re-pair
  4. Restore/verify the stored pairing configuration file wasn't lost or emptied

Example fix

// before
await session.EnsureOpenAsync(ct);
await session.SendAsync(keyCmd, ct);
// after
if (!configuration.HasPairing)
    await pairingUi.RunPairingAsync(ct); // stores the token
await session.EnsureOpenAsync(ct);
Defensive patterns

Strategy: validation

Validate before calling

if (!configuration.HasPairing)
{
    ShowPairingUi(); // run AuthenticateAsync flow to obtain and store token
    return;
}
await session.EnsureOpenAsync(ct);

Type guard

bool IsPaired(VidaaConfiguration config) => config.HasPairing;

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of mgth/LittleBigMouse@7a42f01d47 (2026-09-16). Data as JSON: /api/errors/2c8d83fed9336b15. Report an issue: GitHub.

Appendix: source

Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/VidaaSession.cs:52

        IReadOnlyList<string> topics,
        CancellationToken cancellationToken)
    {
        await CloseAsync().ConfigureAwait(false);
        var connection = await _transport(
                VidaaConnectionProfile.Request(configuration, credentials), cancellationToken)
            .ConfigureAwait(false);
        connection.MessageReceived += Dispatch;
        _connection = connection;
        await connection.SubscribeAsync(topics, cancellationToken).ConfigureAwait(false);
    }

    /// <summary>Opens the session the stored pairing describes, unless one is already open.</summary>
    /// <exception cref="InvalidOperationException">The device has never been paired.</exception>
    public async Task EnsureOpenAsync(CancellationToken cancellationToken)
    {
        if (Connected) return;
        if (!configuration.HasPairing)
            throw new InvalidOperationException("Pair this Hisense VIDAA device first.");

        await OpenAsync(
            VidaaConnectionProfile.StoredCredentials(configuration),
            VidaaConnectionProfile.ResponseTopics(configuration),
            cancellationToken).ConfigureAwait(false);
    }

    /// <summary>
    /// Publishes on the paired session, opening it if needed and giving the command a second
    /// chance when the write is what reveals the broker dropped the previous one. See
    /// <see cref="StaleConnectionRetry"/>; here a dead session has to be closed before the
    /// stored pairing can open another.
    /// </summary>
    public async Task SendAsync(string topic, string payload, CancellationToken cancellationToken)
    {
        await EnsureOpenAsync(cancellationToken).ConfigureAwait(false);
        await StaleConnectionRetry.SendAsync(
            token => PublishAsync(topic, payload, token),

View on GitHub (pinned to 7a42f01d47)