{"record":{"id":"9c75932a2defafa3","repo":"Devolutions/UniGetUI","slug":"github-authentication-is-required-for-cloud-backup","errorCode":null,"errorMessage":"GitHub authentication is required for cloud backups.","messagePattern":"GitHub authentication is required for cloud backups\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"src/UniGetUI.Interface.IpcApi/IpcBackupApi.cs","lineNumber":485,"sourceCode":"        if (!HasConfiguredGitHubClient())\n        {\n            throw new InvalidOperationException(\n                \"GitHub sign-in is not configured for this build. UNIGETUI_GITHUB_CLIENT_ID is missing.\"\n            );\n        }\n    }\n\n    private static GitHubApiClient CreateAnonymousGitHubClient()\n    {\n        return new GitHubApiClient();\n    }\n\n    private static GitHubApiClient CreateAuthenticatedGitHubClient(string? token = null)\n    {\n        token ??= SecureGHTokenManager.GetToken();\n        if (string.IsNullOrWhiteSpace(token))\n        {\n            throw new InvalidOperationException(\"GitHub authentication is required for cloud backups.\");\n        }\n\n        return new GitHubApiClient(token);\n    }\n\n    private static async Task<GitHubUser> GetAuthenticatedGitHubUserAsync(GitHubApiClient client)\n    {\n        var user = await client.GetCurrentUserAsync();\n        if (!string.IsNullOrWhiteSpace(user.Login))\n        {\n            Settings.SetValue(Settings.K.GitHubUserLogin, user.Login);\n        }\n\n        return user;\n    }\n\n    private static async Task<string> GetCloudBackupContentsAsync(string key)\n    {","sourceCodeStart":467,"sourceCodeEnd":503,"githubUrl":"https://github.com/Devolutions/UniGetUI/blob/9b1d7d0eab91620fc15c86b36676532095936ae3/src/UniGetUI.Interface.IpcApi/IpcBackupApi.cs#L467-L503","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Complete GitHub sign-in (StartGitHubDeviceFlowAsync then CompleteGitHubDeviceFlowAsync) before any cloud-backup operation.","Check IpcGitHubAuthInfo.IsAuthenticated (via GetStatusAsync) before offering cloud-backup actions.","If the token was revoked, sign out and re-authenticate."],"exampleFix":"// before: cloud backup without sign-in\nawait IpcBackupApi.CreateCloudBackupAsync();\n// after: ensure authentication first\nvar status = await IpcBackupApi.GetStatusAsync();\nif (!status.Auth.IsAuthenticated)\n    await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true });\nawait IpcBackupApi.CreateCloudBackupAsync();","handlingStrategy":"validation","validationCode":"var status = await IpcBackupApi.GetStatusAsync();\nif (!status.Auth.IsAuthenticated)\n    await IpcBackupApi.StartGitHubDeviceFlowAsync(new IpcGitHubDeviceFlowRequest { LaunchBrowser = true });","typeGuard":"static bool IsGitHubAuthenticated(IpcGitHubAuthInfo auth) => auth.IsAuthenticated;","tryCatchPattern":"try { await IpcBackupApi.CreateCloudBackupAsync(); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"authentication is required\"))\n{ /* prompt user to sign in, then retry */ }","preventionTips":["Check IsAuthenticated before any cloud-backup operation.","Sign out and re-authenticate if the token was revoked.","Do not expose cloud-backup actions in the UI when not authenticated."],"tags":["github","authentication","token","backup","ipc"],"backgroundTag":null,"analyzedSha":"9b1d7d0eab91620fc15c86b36676532095936ae3","analyzedAt":"2026-08-13T12:19:18.278Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}