mgth/LittleBigMouse · error · InvalidOperationException

Associate a Hisense VIDAA projector first.

Error message

Associate a Hisense VIDAA projector first.

What it means

HisenseVidaaService throws this InvalidOperationException from its Required() helper when a per-projector operation (e.g. PowerOnAsync and other commands) references a projector id whose stored configuration is missing or has no IP address. The service requires an associated (configured, IP-reachable) Hisense VIDAA projector before any device command can run. It is a precondition/state guard, not a network failure.

Solutions

  1. Complete the projector association flow first so the configuration has a valid IpAddress, then retry the call.
  2. Verify the projector id exists in the configuration store and that HisenseVidaaConfiguration.IpAddress is set before invoking service methods.
  3. Fix or re-create the configuration entry if the IP was lost (hand-edited file, migration, reset).
  4. In automation code, check the configuration for a non-empty IpAddress before calling service commands.

Example fix

// before
await service.PowerOnAsync(projectorId);

// after
var cfg = store.Get(projectorId);
if (cfg is null || string.IsNullOrWhiteSpace(cfg.IpAddress))
    throw new InvalidOperationException("Projector not associated: run the VIDAA association flow first.");
await service.PowerOnAsync(projectorId);
Defensive patterns

Strategy: validation

Validate before calling

var cfg = store.Get(projectorId);
bool associated = cfg is not null && !string.IsNullOrWhiteSpace(cfg.IpAddress);
if (!associated)
    throw new InvalidOperationException("Associate the Hisense VIDAA projector (set its IP address) before issuing commands.");

Type guard

static bool IsAssociated(HisenseVidaaConfiguration? c) =>
    c is not null && !string.IsNullOrWhiteSpace(c.IpAddress);

Try / catch

try
{
    await service.PowerOnAsync(id);
}
catch (InvalidOperationException ex) when (ex.Message.Contains("Associate a Hisense VIDAA projector"))
{
    // surface setup instructions to the user
}

Prevention

When it happens

Trigger: Calling PowerOnAsync(id) (or any service method that calls Required(id)) when: the id is not present in _store; the stored HisenseVidaaConfiguration exists but IpAddress is null/empty/whitespace.

Common situations: User added the projector entry but never completed the association/pairing flow that sets the IP address; configuration was migrated or hand-edited and the IP field was lost; caller passes a stale id after the projector config was deleted; automation calls PowerOnAsync before the initial setup UI flow ran.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/HisenseVidaaService.cs:195

        _store.Save(c);
    }
    /// <summary>
    /// Slower burst than Tizen, and the trailing delay is kept: awaiting PowerOnAsync
    /// therefore leaves the projector 150 ms to react before the caller reconnects.
    /// </summary>
    static readonly WakeOnLanOptions WakeOnLanBurst = new()
    {
        PacketCount = 3,
        Port = 9,
        DelayBetweenPackets = TimeSpan.FromMilliseconds(150),
        DelayAfterLastPacket = true,
    };

    public Task PowerOnAsync(string id, CancellationToken ct = default)
    {
        var c=Required(id); if (string.IsNullOrWhiteSpace(c.MacAddress)) throw new InvalidOperationException("Enter the projector Wi-Fi MAC address first."); return WakeOnLan.SendAsync(c.MacAddress, WakeOnLanBurst, cancellationToken: ct);
    }
    HisenseVidaaConfiguration Required(string id) => _store.Get(id) is { } c && !string.IsNullOrWhiteSpace(c.IpAddress) ? c : throw new InvalidOperationException("Associate a Hisense VIDAA projector first.");

    async Task<HisenseVidaaClient> ClientForAsync(string id, HisenseVidaaConfiguration configuration)
    {
        HisenseVidaaClient? previous = null;
        HisenseVidaaClient client;
        lock (_clientLock)
        {
            if (_clients.TryGetValue(id, out client!)
                && SameConnection(client.Configuration, configuration)) return client;

            previous = client;
            client = new HisenseVidaaClient(configuration);
            _clients[id] = client;
        }

        if (previous is not null) await previous.DisposeAsync().ConfigureAwait(false);
        return client;
    }

View on GitHub (pinned to 7a42f01d47)