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

Failed to read initial terminal settings.

Error message

Failed to read initial terminal settings.

What it means

RawModeContext on macOS first calls tcgetattr to snapshot the terminal's current termios settings so they can be restored on Dispose. If tcgetattr fails it throws this IOException, because without the original settings raw mode cannot be safely entered or later restored.

Solutions

  1. Check that the fd is a TTY (isatty) before constructing RawModeContext and fall back to cooked input otherwise
  2. Run with a real terminal: docker run -t, ssh -tt, or a CI step with a pseudo-TTY (e.g. script -q)
  3. Ensure stdin is not redirected/closed when the interactive console component starts
  4. Handle the IOException and degrade to non-interactive input handling

Example fix

// before
using var raw = new RawModeContext(fd); // throws when stdin is a pipe
// after
if (isatty(fd) == 0) { EnableNonInteractiveMode(); }
else using var raw = new RawModeContext(fd);
Defensive patterns

Strategy: try-catch

Validate before calling

[DllImport("libc")] static extern int isatty(int fd);
bool IsTerminal(int fd) => isatty(fd) != 0;

Type guard

bool CanEnterRawMode(int fd) => isatty(fd) != 0;

Try / catch

try { using var raw = new RawModeContext(fd); /* interactive read */ }
catch (System.IO.IOException ex) when (ex.Message.Contains("initial terminal settings")) { UseNonInteractiveMode(); }

Prevention

When it happens

Trigger: Constructing RawModeContext with an fd that is not a terminal or is invalid/closed: redirected stdin/stdout, pipe, background job without controlling tty, or a bogus fd value.

Common situations: Running the interactive app with stdin redirected from a file or pipe, in CI without a TTY, under Docker without -t, or after closing the console stream.

Understand the failure class

Background: "unsupported platform" / "not supported on this platform" errors: what they mean and how to fix them — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/Core/Interop/MacOS/MacOSAnsiConsoleInput.cs:33

    protected override IDisposable EnterRawMode(PosixFileDescriptor fd)
    {
        return new RawModeContext(fd);
    }

    private sealed class RawModeContext : IDisposable
    {
        private readonly int _fd;
        private termios_MacOS _original;
        private bool _isDisposed;

        public RawModeContext(int fd)
        {
            _fd = fd;

            if (Termios_MacOS.tcgetattr(_fd, out termios_MacOS t) != 0)
            {
                throw new System.IO.IOException("Failed to read initial terminal settings.");
            }

            _original = t;

            // Raw mode: disable echo, line buffering, and signal interpretation.
            // With ISIG off the terminal does not generate SIGINT, so Ctrl+C
            // arrives as a 0x03 byte that the base adapter reads and acts on
            // directly. This is robust to GCM not being the terminal's
            // foreground process group.
            //
            // TCSANOW (apply immediately) rather than TCSAFLUSH: this context
            // is entered and disposed around each keystroke read, so the
            // terminal is only raw while we are actively reading. Flushing on
            // every transition would discard typeahead still queued in the tty
            // buffer (e.g. the trailing Enter of a pasted "<down><enter>"),
            // hanging the next read.
            t.c_lflag &= ~(LocalFlags.ECHO | LocalFlags.ICANON | LocalFlags.ISIG);

View on GitHub (pinned to e8ce762cd0)