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

  1. Retry the login and complete the device-code entry at https://github.com/login/device before the code expires.
  2. Use a Personal Access Token instead: run 'git-credential-manager github login --pat' or set the credential directly.
  3. If cancellation was unintentional from tooling, remove code that cancels the prompt CancellationToken (promptCts) while the token task is pending.
  4. 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

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

Related errors


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)