mgth/LittleBigMouse · error · ArgumentException

Enter a valid projector IPv4 address.

Error message

Enter a valid projector IPv4 address.

What it means

FindAsync expects the caller-supplied lastKnownAddress to be a valid IPv4 address, which it parses with Ipv4Address.TryParse to seed the subnet scan. If parsing fails, it throws ArgumentException naming the lastKnownAddress parameter before any network activity.

Solutions

  1. Pass a literal IPv4 address string (e.g. "192.168.1.50") as lastKnownAddress
  2. Validate the address with Ipv4Address.TryParse (or IPAddress.TryParse) before calling FindAsync
  3. Fix the stored setting that supplies the address
  4. Resolve a hostname to an IPv4 via DNS first, then pass the resulting IP

Example fix

// before
var device = await discovery.FindAsync(settings.LastAddress, token);
// after
if (!Ipv4Address.TryParse(settings.LastAddress, out _))
    throw new ArgumentException("Stored address must be an IPv4 address.");
var device = await discovery.FindAsync(settings.LastAddress, token);
Defensive patterns

Strategy: validation

Validate before calling

if (!Ipv4Address.TryParse(lastKnownAddress, out _))
    throw new ArgumentException("Provide a valid IPv4 address.", nameof(lastKnownAddress));

Type guard

bool IsIpv4(string s) => System.Net.IPAddress.TryParse(s, out var a) && a.AddressFamily == AddressFamily.InterNetwork;

Try / catch

try { var d = await discovery.FindAsync(addr, token); }
catch (ArgumentException ex) { showUser(ex.Message); }

Prevention

When it happens

Trigger: Calling FindAsync with a hostname, empty string, IPv6 address, or otherwise malformed lastKnownAddress that Ipv4Address.TryParse rejects.

Common situations: Saving a hostname from mDNS instead of an IP in app settings; stale or hand-edited config containing '192.168.1.' or 'projector.local'; empty field on first run.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at LittleBigMouse.Plugins/LittleBigMouse.Plugin.Vcp.Avalonia/HisenseVidaa/HisenseVidaaDiscovery.cs:53

                lastError = e;
            }
            catch (HttpRequestException e)
            {
                lastError = e;
            }
        }

        throw new HttpRequestException(
            $"No VIDAA descriptor answered at {ipAddress} on ports {string.Join('/', HisenseVidaaProtocol.DescriptorPorts)}.",
            lastError);
    }

    public async Task<HisenseVidaaDevice> FindAsync(
        string lastKnownAddress,
        CancellationToken cancellationToken = default)
    {
        if (!Ipv4Address.TryParse(lastKnownAddress, out var seed))
            throw new ArgumentException("Enter a valid projector IPv4 address.", nameof(lastKnownAddress));

        try
        {
            return await ProbeAsync(lastKnownAddress, cancellationToken).ConfigureAwait(false);
        }
        catch (HttpRequestException)
        {
            // SSDP multicast does not cross routers. Search only the /24 of the
            // last known address, and only the two VIDAA descriptor ports.
        }

        var octets = seed.GetAddressBytes();
        using var deadline = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
        deadline.CancelAfter(TimeSpan.FromSeconds(8));
        using var concurrency = new SemaphoreSlim(48, 48);
        var probes = Enumerable.Range(1, 254)
            .Select(host => ProbeSubnetCandidateAsync(
                $"{octets[0]}.{octets[1]}.{octets[2]}.{host}", concurrency, deadline.Token))

View on GitHub (pinned to 7a42f01d47)