{"record":{"id":"9337443feb7e1732","repo":"git-ecosystem/git-credential-manager","slug":"failed-to-read-initial-terminal-settings-933744","errorCode":null,"errorMessage":"Failed to read initial terminal settings.","messagePattern":"Failed to read initial terminal settings\\.","errorType":"exception","errorClass":"IOException","httpStatus":null,"severity":"error","filePath":"src/Core/Interop/MacOS/MacOSAnsiConsoleInput.cs","lineNumber":33,"sourceCode":"\n    protected override IDisposable EnterRawMode(PosixFileDescriptor fd)\n    {\n        return new RawModeContext(fd);\n    }\n\n    private sealed class RawModeContext : IDisposable\n    {\n        private readonly int _fd;\n        private termios_MacOS _original;\n        private bool _isDisposed;\n\n        public RawModeContext(int fd)\n        {\n            _fd = fd;\n\n            if (Termios_MacOS.tcgetattr(_fd, out termios_MacOS t) != 0)\n            {\n                throw new System.IO.IOException(\"Failed to read initial terminal settings.\");\n            }\n\n            _original = t;\n\n            // Raw mode: disable echo, line buffering, and signal interpretation.\n            // With ISIG off the terminal does not generate SIGINT, so Ctrl+C\n            // arrives as a 0x03 byte that the base adapter reads and acts on\n            // directly. This is robust to GCM not being the terminal's\n            // foreground process group.\n            //\n            // TCSANOW (apply immediately) rather than TCSAFLUSH: this context\n            // is entered and disposed around each keystroke read, so the\n            // terminal is only raw while we are actively reading. Flushing on\n            // every transition would discard typeahead still queued in the tty\n            // buffer (e.g. the trailing Enter of a pasted \"<down><enter>\"),\n            // hanging the next read.\n            t.c_lflag &= ~(LocalFlags.ECHO | LocalFlags.ICANON | LocalFlags.ISIG);\n","sourceCodeStart":15,"sourceCodeEnd":51,"githubUrl":"https://github.com/git-ecosystem/git-credential-manager/blob/e8ce762cd04b4100ae637b5fbf39ef9d0a96561e/src/Core/Interop/MacOS/MacOSAnsiConsoleInput.cs#L15-L51","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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"],"exampleFix":"// before\nusing var raw = new RawModeContext(fd); // throws when stdin is a pipe\n// after\nif (isatty(fd) == 0) { EnableNonInteractiveMode(); }\nelse using var raw = new RawModeContext(fd);","handlingStrategy":"try-catch","validationCode":"[DllImport(\"libc\")] static extern int isatty(int fd);\nbool IsTerminal(int fd) => isatty(fd) != 0;","typeGuard":"bool CanEnterRawMode(int fd) => isatty(fd) != 0;","tryCatchPattern":"try { using var raw = new RawModeContext(fd); /* interactive read */ }\ncatch (System.IO.IOException ex) when (ex.Message.Contains(\"initial terminal settings\")) { UseNonInteractiveMode(); }","preventionTips":["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"],"tags":["terminal","macos","tty","interop"],"backgroundTag":"unsupported-platform","analyzedSha":"e8ce762cd04b4100ae637b5fbf39ef9d0a96561e","analyzedAt":"2026-09-11T17:15:08.753Z","contentChangedAt":"2026-09-11T17:15:08.753Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}