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
- Check that the fd is a TTY (isatty) before constructing RawModeContext and fall back to cooked input otherwise
- Run with a real terminal: docker run -t, ssh -tt, or a CI step with a pseudo-TTY (e.g. script -q)
- Ensure stdin is not redirected/closed when the interactive console component starts
- 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
- Verify stdin is a TTY before enabling interactive console mode
- Don't redirect stdin/stdout when launching apps with interactive prompts
- Use pseudo-TTYs (docker -t, ssh -tt, script -q) in automated environments
- Gate interactive features behind a TTY detection check at startup
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
- Failed to read initial terminal settings.
- Failed to enter raw terminal mode.
- Failed to enter raw terminal mode.
- -1
- ErrorSecNoSuchKeychain
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)