Devolutions/UniGetUI · error · InvalidOperationException

Failed to parse brew info JSON

Error message

Failed to parse brew info JSON

What it means

Homebrew details helper runs 'brew info --json=v2' and parses stdout with JsonNode.Parse; if the result is not a JsonObject (e.g. null, an array, or a parse failure returning null), it throws InvalidOperationException. The process task logger is closed with exit code 1 before throwing.

Source

Thrown at src/UniGetUI.PackageEngine.Managers.Homebrew/Helpers/HomebrewPkgDetailsHelper.cs:36

    protected override void GetDetails_UnSafe(IPackageDetails details)
    {
        using var p = new Process
        {
            StartInfo = _brew.MakeBrewStartInfo($"info --json=v2 {details.Package.Id}"),
        };

        IProcessTaskLogger logger = Manager.TaskLogger.CreateNew(
            Enums.LoggableTaskType.LoadPackageDetails, p);
        p.Start();
        string json = p.StandardOutput.ReadToEnd();
        logger.AddToStdOut(json);
        logger.AddToStdErr(p.StandardError.ReadToEnd());
        p.WaitForExit();

        if (JsonNode.Parse(json) is not JsonObject root)
        {
            logger.Close(1);
            throw new InvalidOperationException("Failed to parse brew info JSON");
        }

        // Try formula first, then cask
        var formula = root["formulae"]?.AsArray().FirstOrDefault();
        var cask = root["casks"]?.AsArray().FirstOrDefault();

        if (formula is JsonObject f)
            _populateFromFormula(details, f);
        else if (cask is JsonObject c)
            _populateFromCask(details, c);

        logger.Close(0);
    }

    private static void _populateFromFormula(IPackageDetails details, JsonObject f)
    {
        details.Description = f["desc"]?.ToString();
        details.License = f["license"]?.ToString();

View on GitHub (pinned to 9b1d7d0eab)

Solutions

  1. Ensure Homebrew is installed and on PATH for the UniGetUI process.
  2. Inspect the captured stdout (logger.AddToStdOut) to see what brew actually returned.
  3. Catch InvalidOperationException in the details helper and degrade to partial details, logging the raw output.

Example fix

// before
if (JsonNode.Parse(json) is not JsonObject root)
    throw new InvalidOperationException("Failed to parse brew info JSON");
// after (still throw, but capture context)
if (JsonNode.Parse(json) is not JsonObject root)
{
    Logger.Warn($"brew info returned non-object JSON: {json}");
    throw new InvalidOperationException("Failed to parse brew info JSON");
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Before parsing, confirm brew produced object-shaped JSON.
// (Cannot fully pre-validate; rely on parse + try-catch.)

Type guard

static bool IsBrewJsonObject(string json)
{
    var node = JsonNode.Parse(json);
    return node is JsonObject;
}

Try / catch

try
{
    if (JsonNode.Parse(json) is not JsonObject root)
        throw new InvalidOperationException("Failed to parse brew info JSON");
}
catch (InvalidOperationException ex)
{
    Logger.Warn($"brew info parse failed. raw='{json}'");
    return details; // partial
}

Prevention

When it happens

Trigger: brew info returns empty output (brew not installed / not on PATH), outputs a JSON array instead of an object, or outputs an error message string that is not JSON.

Common situations: Homebrew not installed so stdout is empty; brew prints a warning line to stdout before JSON; PATH issues on the agent process; brew version that changed JSON shape.

Understand the failure class

Related errors


AI-assisted analysis of Devolutions/UniGetUI@9b1d7d0eab (2026-08-13). Data as JSON: /api/errors/cdbfb6a06e3391a9. Report an issue: GitHub.