git-ecosystem / git-credential-manager

Secure, cross-platform Git credential storage with authentication to GitHub, Azure Repos, and other popular Git hosting services.
Other
6.9k stars 1.82k forks source link

Credential Storage Error #1413

Closed bradlitterell closed 1 year ago

bradlitterell commented 1 year ago

Version

2.3.2

Operating system

Windows

OS version or distribution

Win 11 Enterprise, x64

Git hosting provider(s)

Azure DevOps

Other hosting provider

No response

(Azure DevOps only) What format is your remote URL?

https://{org}.visualstudio.com

Can you access the remote repository directly in the browser?

Yes, I can access the repository

Expected behavior

git fetch succeeds after popping up the GCM authentication window for me to login with my enterprise account.

Actual behavior

git fetch fails. git gcm diagnose reports:

[ OK ] Environment [ OK ] File system [ OK ] Networking [ OK ] Git [FAIL] Credential storage

[!] Encountered an exception [!]
GitCredentialManager.Interop.InteropException: Failed to write item to store. ---> System.ComponentModel.Win32Exception: Not enough memory resources are available to process this command

   --- End of inner exception stack trace ---

   at GitCredentialManager.Interop.Windows.Native.Win32Error.ThrowIfError(Int32 error, String defaultErrorMessage, ITrace2 trace2)

   at GitCredentialManager.Interop.Windows.WindowsCredentialManager.AddOrUpdate(String service, String account, String secret)

   at GitCredentialManager.CredentialStore.AddOrUpdate(String service, String account, String secret)

   at GitCredentialManager.Diagnostics.CredentialStoreDiagnostic.RunInternalAsync(StringBuilder log, IList`1 additionalFiles)

   at GitCredentialManager.Diagnostics.Diagnostic.<RunAsync>d__6.MoveNext()

[*] Diagnostic test log [*]
ICredentialStore instance is of type: CredentialStore

Writing test credential...Deleting test credential... OK

[ OK ] Microsoft authentication (AAD/MSA) [ OK ] GitHub API

Logs

Diagnose log at 2023-09-15T17:51:57Z

AppPath: C:\Program Files\Git\mingw64\bin\git-credential-manager.exe InstallDir: C:\Program Files\Git\mingw64\bin\ Version: 2.3.2


Diagnostic: Environment Skipped: False Success: True Exception: None Log: OSType: Windows OSVersion: 10.0 (build 22621) Reading environment variables... OK Variables: CommonProgramFiles(x86)=C:\Program Files (x86)\Common Files OneDrive=C:\Users\bradlit\OneDrive - Microsoft SESSIONNAME=Console TMP=c:\dev\temp PATHEXT=.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC TEMP=c:\dev\temp MSYSTEM=MINGW64 TERM=xterm-256color PROCESSOR_IDENTIFIER=Intel64 Family 6 Model 126 Stepping 5, GenuineIntel USERDNSDOMAIN=redmond.corp.microsoft.com USERDOMAIN=REDMOND Path=C:/Program Files/Git/mingw64/libexec/git-core;C:\Program Files\Git\mingw64\bin;C:\Program Files\Git\usr\bin;...;C:\WINDOWS\system32;C:\WINDOWS;C:\WINDOWS\System32\Wbem;C:\WINDOWS\System32\WindowsPowerShell\v1.0\;...;C:\Program Files\PowerShell\7\;C:\Program Files\Git\cmd;... PROCESSOR_LEVEL=6 NUMBER_OF_PROCESSORS=8 TMPDIR=c:\dev\temp PROMPT=$P$G ProgramFiles(x86)=C:\Program Files (x86) CommonProgramFiles=C:\Program Files (x86)\Common Files ProgramData=C:\ProgramData ProgramFiles=C:\Program Files (x86) GIT_EXEC_PATH=C:/Program Files/Git/mingw64/libexec/git-core SystemRoot=C:\WINDOWS HOMEDRIVE=C: USERNAME=bradlit PROCESSOR_ARCHITEW6432=AMD64 PROCESSOR_ARCHITECTURE=x86 OS=Windows_NT ComSpec=C:\WINDOWS\system32\cmd.exe SystemDrive=C: windir=C:\WINDOWS ALLUSERSPROFILE=C:\ProgramData


Diagnostic: File system Skipped: False Success: True Exception: None Log: Temporary directory is 'c:\dev\temp\'... Checking basic file I/O... Writing to temporary file 'c:\dev\temp\3ea54db6917be225d4cdd6b0'... OK Reading from temporary file 'c:\dev\temp\3ea54db6917be225d4cdd6b0'... OK Deleting temporary file 'c:\dev\temp\3ea54db6917be225d4cdd6b0'... OK Testing IFileSystem instance... UserHomePath: C:\Users\bradlit UserDataDirectoryPath: C:\Users\bradlit.gcm GetCurrentDirectory(): c:\dev\CombinedTpmTester


Diagnostic: Networking Skipped: False Success: True Exception: None Log: Checking networking and HTTP stack... Creating HTTP client... OK IsNetworkAvailable: True Sending HEAD request to http://example.com...Sending HEAD request to https://example.com... OK OK Acquiring free TCP port... OK Testing local HTTP loopback connections... Creating new HTTP listener for http://localhost:58987/... OK Waiting for loopback connection... OK Writing response... OK Waiting for response data... OK Loopback connection data OK


Diagnostic: Git Skipped: False Success: True Exception: None Log: Getting Git version... OK Git version is '2.42.0.windows.2' Locating current repository... OK Git repository at 'C:/dev/CombinedTpmTester/.git' Listing all Git configuration... OK Git configuration: file:C:/Program Files/Git/etc/gitconfig diff.astextplain.textconv=astextplain file:C:/Program Files/Git/etc/gitconfig filter.lfs.clean=git-lfs clean -- %f file:C:/Program Files/Git/etc/gitconfig filter.lfs.smudge=git-lfs smudge -- %f file:C:/Program Files/Git/etc/gitconfig filter.lfs.process=git-lfs filter-process file:C:/Program Files/Git/etc/gitconfig filter.lfs.required=true file:C:/Program Files/Git/etc/gitconfig http.sslbackend=openssl file:C:/Program Files/Git/etc/gitconfig http.sslcainfo=C:/Program Files/Git/mingw64/etc/ssl/certs/ca-bundle.crt file:C:/Program Files/Git/etc/gitconfig core.autocrlf=true file:C:/Program Files/Git/etc/gitconfig core.fscache=true file:C:/Program Files/Git/etc/gitconfig core.symlinks=true file:C:/Program Files/Git/etc/gitconfig core.editor=notepad2.exe file:C:/Program Files/Git/etc/gitconfig core.safecrlf=false file:C:/Program Files/Git/etc/gitconfig pull.ff=only file:C:/Program Files/Git/etc/gitconfig pull.rebase=false file:C:/Program Files/Git/etc/gitconfig credential.helper=manager file:C:/Program Files/Git/etc/gitconfig credential.https://dev.azure.com.usehttppath=true file:C:/Program Files/Git/etc/gitconfig init.defaultbranch=master file:C:/Program Files/Git/etc/gitconfig trace2.configparams=scalar.,gvfs.,remote.origin.url,user.* file:C:/Program Files/Git/etc/gitconfig trace2.eventtarget=\.\pipe\git-c780ac06-135a-4e9e-ab6c-d41e2d265baa file:C:/Program Files/Git/etc/gitconfig difftool.vscode.cmd=code --wait --diff "$LOCAL" "$REMOTE" file:C:/Program Files/Git/etc/gitconfig difftool.windiff.cmd=windiff.exe "$LOCAL" "$REMOTE" file:C:/Program Files/Git/etc/gitconfig diff.tool=windiff file:C:/Program Files/Git/etc/gitconfig gvfs.telemetry-pipe=vfs-c780ac06-135a-4e9e-ab6c-d41e2d265baa file:C:/Program Files/Git/etc/gitconfig fetch.showforcedupdates=false file:C:/Users/bradlit/.gitconfig user.name=... file:C:/Users/bradlit/.gitconfig user.email=... file:C:/Users/bradlit/.gitconfig filter.lfs.smudge=git-lfs smudge -- %f file:C:/Users/bradlit/.gitconfig filter.lfs.process=git-lfs filter-process file:C:/Users/bradlit/.gitconfig filter.lfs.required=true file:C:/Users/bradlit/.gitconfig filter.lfs.clean=git-lfs clean -- %f file:C:/Users/bradlit/.gitconfig safe.directory=... ... safe.directory list file:C:/Users/bradlit/.gitconfig core.autocrlf=false file:.git/config core.repositoryformatversion=0 file:.git/config core.filemode=false file:.git/config core.bare=false file:.git/config core.logallrefupdates=true file:.git/config core.symlinks=false file:.git/config core.ignorecase=true file:.git/config submodule.active=. ... file:.git/config color.diff.whitespace=red reverse file:.git/config diff.wserrorhighlight=all file:.git/config diff.tool=beyondcompare file:.git/config merge.tool=beyondcompare file:.git/config push.default=upstream file:.git/config userdata.configversion=18


Diagnostic: Credential storage Skipped: False Success: False Exception: GitCredentialManager.Interop.InteropException: Failed to write item to store. ---> System.ComponentModel.Win32Exception: Not enough memory resources are available to process this command --- End of inner exception stack trace --- at GitCredentialManager.Interop.Windows.Native.Win32Error.ThrowIfError(Int32 error, String defaultErrorMessage, ITrace2 trace2) at GitCredentialManager.Interop.Windows.WindowsCredentialManager.AddOrUpdate(String service, String account, String secret) at GitCredentialManager.CredentialStore.AddOrUpdate(String service, String account, String secret) at GitCredentialManager.Diagnostics.CredentialStoreDiagnostic.RunInternalAsync(StringBuilder log, IList`1 additionalFiles) at GitCredentialManager.Diagnostics.Diagnostic.d__6.MoveNext() Log: ICredentialStore instance is of type: CredentialStore Writing test credential...Deleting test credential... OK


Diagnostic: Microsoft authentication (AAD/MSA) Skipped: False Success: True Exception: None Log: Broker is not enabled. Flow type is: Auto Gathering MSAL token cache data... OK CacheDirectory: C:\Users\bradlit\AppData\Local.IdentityService CacheFileName: msal.cache CacheFilePath: C:\Users\bradlit\AppData\Local.IdentityService\msal.cache Creating cache helper... OK Verifying MSAL token cache persistence... OK


Diagnostic: GitHub API Skipped: False Success: True Exception: None Log: Using 'https://github.com/' as API target. Querying '/meta' endpoint... OK

Running with GCM_TRACE=1 & GIT_TRACE=1 found this error:

11:03:16.655173 ...GitCommandBase.cs:49 trace: [ExecuteAsync] Host provider 'Azure Repos' was selected. 11:03:16.657215 ...sHostProvider.cs:125 trace: [StoreCredentialAsync] Storing credential with service=https://tpm2tester.visualstudio.com account=bradlit@microsoft.com... fatal: Failed to write item to store. [0x8] at GitCredentialManager.Interop.Windows.Native.Win32Error.ThrowIfError(Int32 error, String defaultErrorMessage, ITrace2 trace2) at GitCredentialManager.Interop.Windows.WindowsCredentialManager.AddOrUpdate(String service, String account, String secret) at GitCredentialManager.CredentialStore.AddOrUpdate(String service, String account, String secret) at Microsoft.AzureRepos.AzureReposHostProvider.StoreCredentialAsync(InputArguments input) at GitCredentialManager.Commands.StoreCommand.ExecuteInternalAsync(InputArguments input, IHostProvider provider) at GitCredentialManager.Commands.GitCommandBase.d5.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Invocation.AnonymousCommandHandler.d6.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Invocation.InvocationPipeline.<>cDisplayClass4_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>cDisplayClass17_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>cDisplayClass15_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>cDisplayClass12_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>cDisplayClass22_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>cDisplayClass19_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<b18_0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass16_0.<b0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c.<b5_0>d.MoveNext() --- End of stack trace from previous location where exception was thrown --- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.CommandLine.Builder.CommandLineBuilderExtensions.<>c__DisplayClass8_0.<b0>d.MoveNext()

fatal: Not enough memory resources are available to process this command

The error message is wrong - I have 874GB of free disk and 17GB of free RAM.

mjcheetham commented 1 year ago

Hello! Thanks for opening an issue and including diagnose logs.

fatal: Not enough memory resources are available to process this command

This error message is originating from Windows itself. By default Git Credential Manager uses the Windows Credential Manager to store Git tokens.

Although Windows docs do not indicate a limit on the number of tokens in the store, in my testing it seems there is a limit in practice of approximately 1474 generic credentials.

Can you check how many entries you have in the Windows Credential Manager? https://support.microsoft.com/en-us/windows/accessing-credential-manager-1b5c916a-6a16-889f-8581-fc16e8165ac0

You can also run the following command to list all credentials in the Windows store:

cmdkey /list

If you so have many credentials in the store, that cannot be removed, then I can suggest that you try an alternative credential store for GCM to use, such as DPAPI files: https://gh.io/gcm/credstores

bradlitterell commented 1 year ago

I currently have 215 credentials, so not close to the limit. Rebooting seemed to unstick it. So, AFAICT there's a bug there somewhere. Maybe in Windows, maybe in WCM, maybe in GCM.

mjcheetham commented 1 year ago

I currently have 215 credentials, so not close to the limit.

Interesting.. I wonder if this limit is size related, not count (i.e., some credentials are bigger than others so take up more 'room')? Just a guess here.

So, AFAICT there's a bug there somewhere. Maybe in Windows, maybe in WCM, maybe in GCM.

We have had some similar reports from our partners in Visual Studio, who also use the Windows Credential Manager. We will check in with them to see if they had more insight in to the root cause of the problem.

I agree however, this looks like a bug in Windows or WCM more likely. This is the first time we've seen this in GCM and haven't touched the interop code in a long time.

ldennington commented 1 year ago

Closing, as this is not something that can be fixed by the GCM project. Workaround exists to use alternative credential store.

TheJCAB commented 5 months ago

FWIW, I just experienced something similar. Same error, exception and callstack. Remote commands (push, fetch) would pop the authentication dialog every time and the commands often (not always) would fail after that anyway.

On a whim I tried running "git fetch" elevated, and that seems to have resolved the issue. Not sure why. Thought I'd share.