git-ecosystem/git-credential-manager · error · IOException

Failed to read initial console mode on

Error message

Failed to read initial console mode on {ConsoleInName}.

What it means

After opening CONIN$, WindowsAnsiConsoleInput calls Kernel32.GetConsoleMode to capture the original (cooked) console mode so it can be restored later. If GetConsoleMode fails, the handle does not refer to a console, so the constructor throws IOException to avoid entering/exiting raw mode on a non-console device.

Solutions

  1. Run git with a genuine console stdin (don't redirect stdin when interactive auth may occur).
  2. Under mintty/MSYS shells, use winpty (winpty git push) so a real Windows console is provided.
  3. Set GCM_INTERACTIVE=never or pre-provision credentials (wincredman store, PAT in config) so no console input is attempted.
  4. Pre-cache credentials with an interactive run once, then use non-interactive runs in scripts/pipes.

Example fix

// before
type input.txt | git push   // stdin is a pipe -> GetConsoleMode fails
// after
winpty git push             # or: git config credential.credentialStore wincredman
Defensive patterns

Strategy: validation

Validate before calling

if (!Kernel32.GetConsoleMode(consoleIn, out _))
    throw new InvalidOperationException("stdin is not a real console; interactive prompt unavailable.");

Type guard

static bool IsConsoleInput(IntPtr handle) =>
    Kernel32.GetConsoleMode(handle, out _); // pipes/files have no console mode

Try / catch

try { using var input = new WindowsAnsiConsoleInput(); ... }
catch (IOException ex) when (ex.Message.Contains("initial console mode"))
{ // stdin redirected: fall back to winpty or non-interactive store
  return NonInteractiveFallback(); }

Prevention

When it happens

Trigger: The CONIN$ handle opened successfully but GetConsoleMode returned false — input is redirected to a file/pipe rather than an actual console buffer, or the handle was closed concurrently.

Common situations: Running git with stdin redirected from a file or pipe (e.g. `git fetch < input.txt`, piping into git) while GCM tries to prompt for input; running under wrappers that fake console handles; unusual terminal emulators (e.g. mintty without winpty) providing pipes instead of console handles.

Understand the failure class

Background: "open() failed", "failed to open file", "cannot create file" — what a file open error means and how to fix it — this error's family across 42 libraries.

Related errors


AI-assisted analysis of git-ecosystem/git-credential-manager@e8ce762cd0 (2026-09-11). Data as JSON: /api/errors/fe6fb5d0b46f9ad6. Report an issue: GitHub.

Appendix: source

Thrown at src/Core/Interop/Windows/WindowsAnsiConsoleInput.cs:85

        _handle = Kernel32.CreateFile(
            fileName: ConsoleInName,
            desiredAccess: NativeFileAccess.GenericRead | NativeFileAccess.GenericWrite,
            shareMode: NativeFileShare.Read | NativeFileShare.Write,
            securityAttributes: IntPtr.Zero,
            creationDisposition: FileCreationDisposition.OpenExisting,
            flagsAndAttributes: NativeFileAttributes.Normal,
            templateFile: IntPtr.Zero);

        if (_handle.IsInvalid)
        {
            _handle.Dispose();
            throw new IOException($"Failed to open {ConsoleInName} for reading.");
        }

        if (!Kernel32.GetConsoleMode(_handle, out _originalMode))
        {
            _handle.Dispose();
            throw new IOException($"Failed to read initial console mode on {ConsoleInName}.");
        }

        // The console is left in its normal (cooked) mode except during an
        // active keystroke read (see ReadKey). That is what keeps Ctrl+C working
        // when GCM is doing other work — MSAL polling, a GUI, the network — and
        // not just while a Spectre prompt happens to be reading: with
        // ProcessedInput on, Ctrl+C raises CTRL_C_EVENT and the runtime's
        // default handler terminates the process.
    }

    // Switch the console into raw mode (no echo, no line input, no system Ctrl+C
    // handling) for the duration of a read. Caller must hold _modeLock.
    private void EnterRawMode()
    {
        ConsoleMode rawMode = _originalMode
            & ~(ConsoleMode.LineInput | ConsoleMode.EchoInput | ConsoleMode.ProcessedInput);

        if (!Kernel32.SetConsoleMode(_handle, rawMode))

View on GitHub (pinned to e8ce762cd0)