Devolutions/UniGetUI · error · InvalidDataException
JsonNode? pkg was null, when it shouldn't
Error message
JsonNode? pkg was null, when it shouldn't
What it means
SerializableBundle.LoadFromJson deserializes an exported UniGetUI bundle (export_version, expected 3). It reads the 'packages' JSON array via AsArray2 and iterates JsonNode? elements. System.Text.Json yields a null JsonNode for every JSON `null` literal element; the loop treats any null as corrupt data and throws InvalidDataException. Unlike the listing timeouts, this throw is NOT caught here — it propagates to the caller doing the bundle import.
Source
Thrown at src/UniGetUI.PackageEngine.Serializable/SerializableBundle.cs:52
export_version = this.export_version,
packages = _packages,
incompatible_packages_info = this.incompatible_packages_info,
incompatible_packages = _incompatPackages,
};
}
public override void LoadFromJson(JsonNode data)
{
this.export_version = data[nameof(export_version)]?.GetVal<double>() ?? 0;
this.incompatible_packages_info =
data[nameof(incompatible_packages_info)]?.GetVal<string>() ?? IncompatMessage;
this.packages = new List<SerializablePackage>();
this.incompatible_packages = new List<SerializableIncompatiblePackage>();
foreach (JsonNode? pkg in data[nameof(packages)]?.AsArray2() ?? new())
{
if (pkg is null)
throw new InvalidDataException("JsonNode? pkg was null, when it shouldn't");
packages.Add(new SerializablePackage(pkg));
}
foreach (JsonNode? inc_pkg in data[nameof(incompatible_packages)]?.AsArray2() ?? new())
{
if (inc_pkg is null)
throw new InvalidDataException("JsonNode? inc_pkg was null, when it shouldn't");
incompatible_packages.Add(new SerializableIncompatiblePackage(inc_pkg));
}
}
public override JsonObject AsJsonNode()
{
JsonObject obj = new();
obj.Add(nameof(export_version), export_version);
obj.Add(
nameof(packages),
new JsonArray(packages.Select(p => p.AsJsonNode()).ToArray())View on GitHub (pinned to 9b1d7d0eab)
Solutions
- Regenerate the bundle export from a working UniGetUI instance and re-import.
- Pre-clean the file: remove null elements from the 'packages' (and 'incompatible_packages') arrays before import.
- Verify export_version equals SerializableBundle.ExpectedVersion (3); an older/incompatible format is a frequent root cause of malformed arrays.
- If null slots are acceptable gaps in your workflow, relax the throw to `if (pkg is null) continue;` so corrupt slots are skipped instead of aborting the whole import.
- Diff the failing file against a known-good export to find which element is null.
Example fix
// before (SerializableBundle.cs:49-54)
foreach (JsonNode? pkg in data[nameof(packages)]?.AsArray2() ?? new())
{
if (pkg is null)
throw new InvalidDataException("JsonNode? pkg was null, when it shouldn't");
packages.Add(new SerializablePackage(pkg));
}
// after — skip corrupt null slots instead of aborting the entire import
foreach (JsonNode? pkg in data[nameof(packages)]?.AsArray2() ?? new())
{
if (pkg is null) continue;
packages.Add(new SerializablePackage(pkg));
} Defensive patterns
Strategy: validation
Validate before calling
// Strip null elements from the 'packages' array before deserializing.
static JsonNode SanitizeBundle(JsonNode node)
{
if (node is JsonObject obj && obj["packages"] is JsonArray pkgs)
{
JsonArray clean = new();
foreach (var p in pkgs.Where(n => n is not null))
clean.Add(p.DeepClone());
obj["packages"] = clean;
}
if (node is JsonObject obj2 && obj2["export_version"]?.GetVal<double>() != SerializableBundle.ExpectedVersion)
throw new InvalidDataException($"Unexpected bundle export_version");
return node;
}
var safe = SanitizeBundle(JsonNode.Parse(File.ReadAllText(path))!);
var bundle = new SerializableBundle(safe); Type guard
static bool BundlePackagesHaveNoNulls(JsonNode node)
{
if (node is not JsonObject obj) return false;
if (obj["packages"] is not JsonArray arr) return true; // absent array is fine
return arr.All(e => e is not null);
} Try / catch
try
{
var bundle = new SerializableBundle(JsonNode.Parse(json)!);
}
catch (InvalidDataException ex) when (ex.Message.Contains("pkg was null"))
{
Logger.Error("Bundle file has null package entries; refusing to import corrupt file.");
// re-export instead of importing partial data
} Prevention
- Always import bundles produced by the same UniGetUI major version (export_version == 3).
- Validate the file is complete (no truncation) before import — check it ends with a closing brace and parses cleanly.
- Do not hand-edit exported bundle JSON; regenerate it instead.
- Add a schema/null-element check in any tooling that writes bundles so null slots never reach LoadFromJson.
When it happens
Trigger: Constructing `new SerializableBundle(node)` or calling LoadFromJson(node) where node["packages"] is a JSON array containing at least one null element, e.g. `{"export_version":3,"packages":[null,{"Id":"x"}]}`. AsArray2 only reshapes scalar/empty-object nodes into arrays; it does not strip null array elements.
Common situations: A bundle export file truncated by a crash mid-write; hand-editing the export JSON and leaving a trailing comma or empty slot that serializes as null; importing a bundle produced by a different/older UniGetUI version whose exporter emitted sparse arrays; concatenating export fragments leaving null placeholders.
Related errors
- JsonNode? inc_pkg was null, when it shouldn't
- GitHub returned an empty response.
- Exactly one of content or path must be supplied when importi
- The bundle format "{format}" is not supported.
- The bundle content could not be parsed.
AI-assisted analysis of Devolutions/UniGetUI@9b1d7d0eab (2026-08-13).
Data as JSON: /api/errors/0412fa68838d8887.
Report an issue: GitHub.