git-ecosystem/git-credential-manager · warning · Trace2InvalidOperationException
User canceled device code authentication
Error message
User canceled device code authentication
What it means
During the GitHub OAuth device-code flow, GetOAuthTokenViaDeviceCodeAsync awaits the token task while showing a prompt to the user. If the user cancels the operation (closes the dialog or cancels the device-code prompt), the awaited task throws OperationCanceledException, which the code rethrows as a Trace2InvalidOperationException with this message.
Solutions
- Retry the login and complete the device-code entry at https://github.com/login/device before the code expires.
- Use a Personal Access Token instead: run 'git-credential-manager github login --pat' or set the credential directly.
- If cancellation was unintentional from tooling, remove code that cancels the prompt CancellationToken (promptCts) while the token task is pending.
- Clear stale credentials and re-run authentication: 'git-credential-manager github logout' then log in again.
Example fix
// before (user closed device dialog, token never obtained) // after: choose a non-interactive path or complete the flow git-credential-manager github logout git-credential-manager github login --device // then enter the code promptly
Defensive patterns
Strategy: try-catch
Try / catch
try
{
var token = await githubAuth.GetOAuthTokenViaDeviceCodeAsync(targetUri, scopes);
}
catch (OperationCanceledException)
{
// user cancelled the device-code prompt; fall back to PAT flow
}
catch (InvalidOperationException ex) when (ex.Message.Contains("User canceled device code"))
{
// same: prompt user to retry or supply a PAT
} Prevention
- Instruct users to complete the code entry before the device code expires
- Offer a PAT fallback whenever device flow may be cancelled
- Avoid programmatically cancelling the prompt CTS while the token task is pending
- Show clear instructions with the device code URL and expiry
When it happens
Trigger: User presses Cancel or closes the device-code dialog window while GCM is polling GitHub for the device-flow token; the CancellationToken passed to the device prompt is triggered before the token result arrives.
Common situations: Users abandoning the 'enter code at github.com/login/device' flow because the dialog was confusing or they wanted to use a PAT instead; automation that programmatically cancels the prompt CTS after a timeout.
Understand the failure class
- Authentication and authorization failures — expired tokens, bad credentials, and missing scopes.
Related errors
- User cancelled dialog.
- User canceled device code authentication
- User cancelled dialog.
- Browser authentication requires a desktop session
- User cancelled dialog.
AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11).
Data as JSON: /api/errors/d4aeaa4aa410668c.
Report an issue: GitHub.
Appendix: source
Thrown at src/GitHub/GitHubAuthentication.cs:484
// Start the request for an OAuth token but don't wait
Task<OAuth2TokenResult> tokenTask = oauthClient.GetTokenByDeviceCodeAsync(dcr, tokenCts.Token);
Task t = await Task.WhenAny(promptTask, tokenTask);
// If the dialog was closed the user wishes to cancel the request
if (t == promptTask)
{
tokenCts.Cancel();
}
OAuth2TokenResult tokenResult;
try
{
tokenResult = await tokenTask;
}
catch (OperationCanceledException)
{
throw new Trace2InvalidOperationException(Context.Trace2,
"User canceled device code authentication");
}
// Close the dialog
promptCts.Cancel();
return tokenResult;
}
return await GetOAuthTokenViaDeviceCodeViaTtyAsync(oauthClient, dcr);
}
private Task ShowDeviceCodeViaUiAsync(OAuth2DeviceCodeResult dcr, CancellationToken ct)
{
var viewModel = new DeviceCodeViewModel(Context.SessionManager)
{
UserCode = dcr.UserCode,
VerificationUrl = dcr.VerificationUri.ToString(),View on GitHub (pinned to e8ce762cd0)