Devolutions/UniGetUI · warning · InvalidOperationException

The cloud backup \"{key}\" was not found.

Error message

The cloud backup \"{key}\" was not found.

What it means

GetCloudBackupContentsAsync locates the backup gist (found), fetches the full gist via GetGistAsync, then searches gist.Files for an entry whose key StartsWith the package-backup prefix and EndsWith the requested key. If no matching file is found, or the file's Content is null, it throws InvalidOperationException with the key in the message. This means the gist exists but does not contain a backup for the specified machine/device key.

Source

Thrown at src/UniGetUI.Interface.IpcApi/IpcBackupApi.cs:519

    private static async Task<string> GetCloudBackupContentsAsync(string key)
    {
        using var client = CreateAuthenticatedGitHubClient();
        await GetAuthenticatedGitHubUserAsync(client);
        var backupGist = await GetBackupGistAsync(client, createIfMissing: false);
        if (backupGist is null)
        {
            throw new InvalidOperationException("No cloud backups are available for the current account.");
        }

        var fullGist = await client.GetGistAsync(backupGist.Id);
        var file = fullGist.Files.FirstOrDefault(candidate =>
            candidate.Key.StartsWith(PackageBackupStartingKey, StringComparison.Ordinal)
            && candidate.Key.EndsWith(key, StringComparison.Ordinal));

        if (file.Value?.Content is null)
        {
            throw new InvalidOperationException($"The cloud backup \"{key}\" was not found.");
        }

        return file.Value.Content;
    }

    private static async Task<GitHubGist?> GetBackupGistAsync(
        GitHubApiClient client,
        bool createIfMissing
    )
    {
        var candidates = await client.GetCurrentUserGistsAsync();
        var backupGist = candidates.FirstOrDefault(candidate =>
            candidate.Description?.EndsWith(GistDescriptionEndingKey, StringComparison.Ordinal)
            == true
        );

        if (backupGist is not null || !createIfMissing)
        {

View on GitHub (pinned to 9b1d7d0eab)

Solutions

  1. Call ListCloudBackupsAsync to enumerate the valid keys present in the gist, then use one of those.
  2. Verify the key matches the display value from the backup list (it is derived from MachineName\UserName).
  3. If the key changed due to a machine/user rename, create a new backup from the current machine first.

Example fix

// before: guessing a backup key
await IpcBackupApi.DownloadCloudBackupAsync(new IpcCloudBackupRequest { Key = "old-pc" });
// after: select from the available list
var entries = await IpcBackupApi.ListCloudBackupsAsync();
var entry = entries.FirstOrDefault(e => e.IsCurrentMachine) ?? entries.FirstOrDefault();
if (entry is not null)
    await IpcBackupApi.DownloadCloudBackupAsync(new IpcCloudBackupRequest { Key = entry.Key });
Defensive patterns

Strategy: validation

Validate before calling

var entries = await IpcBackupApi.ListCloudBackupsAsync();
var validKeys = entries.Select(e => e.Key).ToHashSet(StringComparer.OrdinalIgnoreCase);
if (!validKeys.Contains(request.Key))
    throw new ArgumentException($"Backup key '{request.Key}' not found.");

Type guard

static bool IsValidBackupKey(string key, IReadOnlyList<IpcCloudBackupEntry> entries) =>
    entries.Any(e => e.Key.Equals(key, StringComparison.OrdinalIgnoreCase));

Try / catch

try { await IpcBackupApi.DownloadCloudBackupAsync(request); }
catch (InvalidOperationException ex) when (ex.Message.Contains("was not found"))
{ /* key is wrong; re-list and pick a valid one */ }

Prevention

When it happens

Trigger: DownloadCloudBackupAsync or RestoreCloudBackupAsync is called with a key that does not match any file in the backup gist. The key is from a different machine, was mistyped, or the corresponding backup file was removed from the gist.

Common situations: The user tries to restore from a machine key that was never backed up to this gist. The key was typed incorrectly. The backup file for that machine was manually removed from the gist. The user switched machines and the device identifier (MachineName\UserName) changed, producing a different key.

Related errors


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