Devolutions/UniGetUI · error · InvalidOperationException
GitHub sign-in did not complete successfully. Finish the dev
Error message
GitHub sign-in did not complete successfully. Finish the device authorization and try again.
What it means
CompleteGitHubDeviceFlowAsync wraps the token-exchange and user-fetch logic in a try/catch (Exception). If any exception occurs inside the try block — HttpRequestException from the token endpoint, the empty-token InvalidOperationException, an error from GetCurrentUserAsync, or a SecureGHTokenManager failure — it is logged and re-thrown as a new InvalidOperationException with this generic message. The original exception's type and detail are lost to the caller (only logged).
Source
Thrown at src/UniGetUI.Interface.IpcApi/IpcBackupApi.cs:250
var user = await userClient.GetCurrentUserAsync();
Settings.SetValue(Settings.K.GitHubUserLogin, user.Login ?? string.Empty);
ClearPendingGitHubDeviceFlow();
return new IpcGitHubAuthResult
{
Status = "success",
Command = "complete-github-sign-in",
Message = string.IsNullOrWhiteSpace(user.Login)
? "GitHub sign-in completed."
: $"GitHub sign-in completed for {user.Login}.",
Auth = await GetGitHubAuthInfoAsync(),
};
}
catch (Exception ex)
{
Logger.Error("An error occurred while completing GitHub device flow sign-in:");
Logger.Error(ex);
throw new InvalidOperationException(
"GitHub sign-in did not complete successfully. Finish the device authorization and try again."
);
}
}
public static async Task<IpcGitHubAuthResult> SignOutGitHubAsync()
{
Settings.SetValue(Settings.K.GitHubUserLogin, "");
SecureGHTokenManager.DeleteToken();
ClearPendingGitHubDeviceFlow();
return new IpcGitHubAuthResult
{
Status = "success",
Command = "sign-out-github",
Message = "GitHub sign-out complete.",
Auth = await GetGitHubAuthInfoAsync(),
};View on GitHub (pinned to 9b1d7d0eab)
Solutions
- Check the application logs (Logger.Error output) for the original exception that was swallowed — the re-thrown message is generic.
- Retry the complete flow; most causes (network, timing) are transient.
- Restart the device flow (StartGitHubDeviceFlowAsync) if retries fail, in case the device code or token is stale.
- Verify network connectivity and that UNIGETUI_GITHUB_CLIENT_ID is correctly configured.
Defensive patterns
Strategy: try-catch
Try / catch
try { await IpcBackupApi.CompleteGitHubDeviceFlowAsync(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("did not complete successfully"))
{ /* inspect logs for the original swallowed exception; restart the flow */ } Prevention
- Check Logger.Error output for the root cause — the re-thrown exception hides it.
- Restart the device flow if the generic completion error persists.
- Verify network connectivity and client-ID configuration before retrying.
When it happens
Trigger: Any exception is thrown within the try block of CompleteGitHubDeviceFlowAsync: network failure contacting GitHub, expired/revoked token, empty access token, failure to fetch the current user, or an error storing the token securely. The catch-all wraps all of these into a single generic message.
Common situations: Transient network error during token exchange. The user did not complete authorization and the token endpoint returned an error. The stored token was invalid. GetCurrentUserAsync failed with 401/403. The original root cause must be found in the logs (Logger.Error) since the re-thrown exception does not preserve it as InnerException.
Related errors
- The pending GitHub device flow has expired. Start sign-in ag
- GitHub did not return an access token.
- No GitHub device flow is pending. Start sign-in first.
- GitHub sign-in is not configured for this build. UNIGETUI_GI
- GitHub authentication is required for cloud backups.
AI-assisted analysis of Devolutions/UniGetUI@9b1d7d0eab (2026-08-13).
Data as JSON: /api/errors/00e568a07c49c19b.
Report an issue: GitHub.