-
-
Notifications
You must be signed in to change notification settings - Fork 0
Fix "device not configured" error on macOS when terminal state is invalid #58
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
… PTY operations Co-authored-by: joelklabo <264977+joelklabo@users.noreply.github.com>
Co-authored-by: joelklabo <264977+joelklabo@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR addresses the "device not configured" (ENXIO) error that occurs on macOS when the terminal state is invalid. The fix adds validation to ensure terminal file descriptors are actually usable before attempting PTY operations.
Key Changes:
- Enhanced
IsTTY()function to validate terminal state usingterm.GetState()in addition to checking if stdin/stdout are terminals - Added test coverage for terminal state validation and pipe fallback behavior
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
internal/execx/run.go |
Enhanced IsTTY() with term.GetState() validation to detect invalid terminal states and gracefully fall back to pipe mode |
internal/execx/run_test.go |
Added tests for terminal state validation and pipe fallback behavior |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| // If GetState fails, the terminal might be in an invalid state (closed/detached). | ||
| if _, err := term.GetState(stdinFd); err != nil { | ||
| return false | ||
| } |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation only validates the state of stdin, but not stdout. Since the function checks that both stdin AND stdout are terminals (line 15), it should also verify that stdout's state can be retrieved. If stdout is a terminal but in an invalid state, this could still lead to PTY initialization failures.
Consider adding a similar state check for stdout to ensure both file descriptors are usable before attempting PTY operations.
| } | |
| } | |
| if _, err := term.GetState(stdoutFd); err != nil { | |
| return false | |
| } |
| func TestIsTTY_ValidatesTerminalState(t *testing.T) { | ||
| // This test verifies that IsTTY() not only checks if stdin/stdout are terminals, | ||
| // but also validates that we can actually get the terminal state. | ||
| // This prevents "device not configured" errors when terminals are in an invalid state. | ||
|
|
||
| // In a normal test environment, stdin/stdout are not terminals. | ||
| // So IsTTY should return false. | ||
| if IsTTY() { | ||
| t.Skip("Running in a TTY environment; can't test non-TTY behavior") | ||
| } | ||
|
|
||
| // Verify that if stdin is a terminal, we can get its state. | ||
| stdinFd := int(os.Stdin.Fd()) | ||
| if term.IsTerminal(stdinFd) { | ||
| if _, err := term.GetState(stdinFd); err != nil { | ||
| // If we can't get the state, IsTTY should return false | ||
| if IsTTY() { | ||
| t.Error("IsTTY() returned true even though GetState failed") | ||
| } | ||
| } | ||
| } | ||
| } |
Copilot
AI
Dec 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test does not effectively validate the fix for the "device not configured" issue. The test logic on lines 17-30 has a problem: if IsTTY() returns false initially (line 17), the code will skip. Otherwise, it checks if stdin is a terminal and if GetState fails - but if GetState fails, IsTTY() would have already returned false, so line 26 would never execute the error condition.
The test doesn't simulate the actual problematic scenario where term.IsTerminal() returns true but term.GetState() fails (the invalid terminal state that causes ENXIO). Consider using a mock or creating a test that can actually trigger this condition, or alternatively, remove this test since the second test (TestRun_FallsBackToPipesWhenPTYUnavailable) already provides basic coverage for the fallback behavior.
The shim fails with ENXIO ("device not configured") when
term.IsTerminal()reports stdin/stdout as TTYs but the underlying terminal device is closed, detached, or otherwise invalid—triggering whenpty.Start()attempts PTY operations.Changes
internal/execx/run.go: Addedterm.GetState()validation inIsTTY()to verify terminal is actually usable before attempting PTY operations. Falls back to pipe mode when state check fails.internal/execx/run_test.go: Added test coverage for terminal state validation logic.This prevents PTY initialization failures while maintaining full PTY support for valid terminals.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
version/usr/bin/curl /usr/bin/curl version --64 tachttool -I EhXc9oXdH cfg share/ackchyually/shims/git --gdwarf-5 --64 -o share/ackchyually/shims/git -I kchyually/internal/eval/helpcount/helpcount.go kchyually/internal/eval/helpcount/scenarios.go /share/ackchyually/shims/git --gdwarf-5 --64 -o /share/ackchyually/shims/git(dns block)/usr/bin/curl /usr/bin/curl version x86_64-linux-gnu-B ly/shims/git -W _.a eN7yY1GM7 4588/work/bin/exit0tool . /internal/app --64 4588/work/bin/exeval@example.com rtcf�� cN-YpiLin x64/src/crypto/internal/fips140/nistec/fiat/cast.go /share/ackchyually/shims/git --gdwarf-5 --64 -o /share/ackchyualEval(dns block)/usr/bin/curl /usr/bin/curl version 6576090/b131/_x0-B tachttool 6576�� _.a /tmp/go-build2576576090/b131/ 4588/work/bin/exit0tool . --gdwarf2 --64 4588/work/bin/ex-b -plu�� /usr/libexec/gcc/x86_64-linux-gn--detach CZgK7V3yW ly/shims/git -plugin-opt=-pas/usr/bin/sh -plugin-opt=-pas-c -plugin-opt=-pasgit status ly/shims/git(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.