Devolutions/UniGetUI · error · NullResponseException
Null response for package {packageId}
Error message
Null response for package {packageId} What it means
CratesIOClient.GetManifest throws NullResponseException when the /crates/{id} JSON deserializes successfully but the 'crate' object is null. This indicates crates.io returned a well-formed but semantically empty payload (e.g. the crate was yanked/deleted, or an unexpected schema).
Source
Thrown at src/UniGetUI.PackageEngine.Managers.Cargo/CratesIOClient.cs:74
internal sealed class CargoManifestPublisher
{
public string? avatar { get; init; }
public required string name { get; init; }
public string? url { get; init; }
}
internal sealed class CratesIOClient
{
public const string ApiUrl = "https://crates.io/api/v1";
internal static string? TEST_ApiUrlOverride { private get; set; }
public static Tuple<Uri, CargoManifest> GetManifest(string packageId)
{
var manifestUrl = new Uri($"{GetApiUrl()}/crates/{packageId}");
var manifest = Fetch<CargoManifest>(manifestUrl);
if (manifest.crate is null)
{
throw new NullResponseException($"Null response for package {packageId}");
}
return Tuple.Create(manifestUrl, manifest);
}
public static CargoManifestVersion GetManifestVersion(string packageId, string version)
{
var manifestUrl = new Uri($"{GetApiUrl()}/crates/{packageId}/{version}");
var manifest = Fetch<CargoManifestVersionWrapper>(manifestUrl);
if (manifest.version is null)
{
throw new NullResponseException($"Null response for package {packageId}");
}
return manifest.version;
}
private static string GetApiUrl() => TEST_ApiUrlOverride ?? ApiUrl;
internal static T Fetch<T>(Uri url)View on GitHub (pinned to 9b1d7d0eab)
Solutions
- Verify the crate exists at https://crates.io/crates/{packageId} before fetching.
- Catch NullResponseException in the Cargo details helper and return a degraded details object.
- Retry once on transient empty responses; if it persists, surface 'details unavailable'.
Example fix
// before
var (url, manifest) = CratesIOClient.GetManifest(packageId);
// after
try { (url, manifest) = CratesIOClient.GetManifest(packageId); }
catch (NullResponseException) { return details with { Name = package.Id }; } Defensive patterns
Strategy: try-catch
Validate before calling
// Validate crate exists before fetching the manifest. // (No cheap check; crates.io has no 'exists' endpoint — rely on try-catch.)
Try / catch
try
{
var (url, manifest) = CratesIOClient.GetManifest(packageId);
}
catch (NullResponseException ex)
{
Logger.Warn($"No crate manifest for {packageId}: {ex.Message}");
return details with { Name = package.Id, Description = "Details unavailable" };
} Prevention
- Verify the crate id against the search results list before fetching details.
- Catch NullResponseException in the Cargo details helper to degrade gracefully.
- Retry once on transient empty responses from crates.io.
When it happens
Trigger: Fetching Cargo package details for an id whose crates.io manifest has no 'crate' field, or a 200 response with an error-shaped body.
Common situations: Looking up a crate that was renamed/yanked; transient crates.io anomaly; packageId casing/typo that resolves to an empty manifest.
Related errors
- Null response for request to {url}
- The updater download server returned an invalid partial cont
- The updater download server returned partial content with a
- GitHub request failed with HTTP {(int)response.StatusCode} (
- The current UniGetUI session cannot open package details.
AI-assisted analysis of Devolutions/UniGetUI@9b1d7d0eab (2026-08-13).
Data as JSON: /api/errors/4d44f1cce2081898.
Report an issue: GitHub.