Devolutions/UniGetUI · warning · InvalidOperationException

GitHub authentication is required for cloud backups.

Error message

GitHub authentication is required for cloud backups.

What it means

CreateAuthenticatedGitHubClient retrieves a token via SecureGHTokenManager.GetToken() (unless one is passed in). If the token is null or whitespace, it throws InvalidOperationException. Every cloud-backup operation (create, list, download, restore) and GetAuthenticatedGitHubUserAsync flow through this method, so the error surfaces as a precondition failure before any GitHub API call is made.

Source

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

        if (!HasConfiguredGitHubClient())
        {
            throw new InvalidOperationException(
                "GitHub sign-in is not configured for this build. UNIGETUI_GITHUB_CLIENT_ID is missing."
            );
        }
    }

    private static GitHubApiClient CreateAnonymousGitHubClient()
    {
        return new GitHubApiClient();
    }

    private static GitHubApiClient CreateAuthenticatedGitHubClient(string? token = null)
    {
        token ??= SecureGHTokenManager.GetToken();
        if (string.IsNullOrWhiteSpace(token))
        {
            throw new InvalidOperationException("GitHub authentication is required for cloud backups.");
        }

        return new GitHubApiClient(token);
    }

    private static async Task<GitHubUser> GetAuthenticatedGitHubUserAsync(GitHubApiClient client)
    {
        var user = await client.GetCurrentUserAsync();
        if (!string.IsNullOrWhiteSpace(user.Login))
        {
            Settings.SetValue(Settings.K.GitHubUserLogin, user.Login);
        }

        return user;
    }

    private static async Task<string> GetCloudBackupContentsAsync(string key)
    {

View on GitHub (pinned to 9b1d7d0eab)

Solutions

  1. Complete GitHub sign-in (StartGitHubDeviceFlowAsync then CompleteGitHubDeviceFlowAsync) before any cloud-backup operation.
  2. Check IpcGitHubAuthInfo.IsAuthenticated (via GetStatusAsync) before offering cloud-backup actions.
  3. If the token was revoked, sign out and re-authenticate.

Example fix

// before: cloud backup without sign-in
await IpcBackupApi.CreateCloudBackupAsync();
// after: ensure authentication first
var status = await IpcBackupApi.GetStatusAsync();
if (!status.Auth.IsAuthenticated)
    await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true });
await IpcBackupApi.CreateCloudBackupAsync();
Defensive patterns

Strategy: validation

Validate before calling

var status = await IpcBackupApi.GetStatusAsync();
if (!status.Auth.IsAuthenticated)
    await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true });

Type guard

static bool IsGitHubAuthenticated(IpcGitHubAuthInfo auth) => auth.IsAuthenticated;

Try / catch

try { await IpcBackupApi.CreateCloudBackupAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("authentication is required"))
{ /* prompt user to sign in, then retry */ }

Prevention

When it happens

Trigger: A cloud-backup operation (CreateCloudBackupAsync, ListCloudBackupsAsync, DownloadCloudBackupAsync, RestoreCloudBackupAsync) or GetGitHubAuthInfoAsync's lazy user fetch is invoked when no GitHub token is stored — i.e. the user has not completed the device flow, or has signed out.

Common situations: The user attempts a cloud backup before signing in. The user signed out (SignOutGitHubAsync deletes the token) and then tried a backup. The secure storage was cleared or corrupted. The token expired and SecureGHTokenManager no longer returns a value.

Understand the failure class

Related errors


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