Skip to content

Commit 6ec4228

Browse files
dfa1claude
andcommitted
fix(cli): clearer Windows TUI error on Git Bash / MinTTY
GetConsoleMode only works on real Windows console handles. Git Bash, MSYS and other MinTTY-based shells pipe stdio through the terminal emulator instead of attaching a console, so the call fails with ERROR_INVALID_HANDLE and the TUI aborts with a bare "GetConsoleMode failed" message that leaves users at a dead end. Detect that case via GetFileType: if the stdio handle returns FILE_TYPE_PIPE the user is on MinTTY-piped stdio, so throw an actionable IOException pointing at `winpty <command>` or the terminals that do attach a real console (Windows Terminal, PowerShell, cmd.exe). Add a paragraph to docs/how-to.md under the TUI section covering the same workaround so users finding the docs first don't trip on it. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
1 parent cde845b commit 6ec4228

2 files changed

Lines changed: 33 additions & 0 deletions

File tree

cli/src/main/java/io/github/dfa1/vortex/cli/tui/term/WindowsTerminal.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@ public final class WindowsTerminal implements Terminal {
3434
private static final int ENABLE_PROCESSED_OUTPUT = 0x0001;
3535
private static final int ENABLE_VIRTUAL_TERMINAL_PROCESSING = 0x0004;
3636

37+
private static final int FILE_TYPE_PIPE = 0x0003;
38+
3739
private static final Linker LINKER = Linker.nativeLinker();
3840
private static final SymbolLookup KERNEL32 = SymbolLookup.libraryLookup(
3941
"kernel32", Arena.global());
@@ -47,6 +49,8 @@ public final class WindowsTerminal implements Terminal {
4749
private static final MethodHandle GET_CONSOLE_SCREEN_BUFFER_INFO = downcall(
4850
"GetConsoleScreenBufferInfo",
4951
FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS));
52+
private static final MethodHandle GET_FILE_TYPE = downcall("GetFileType",
53+
FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS));
5054

5155
private final Arena arena;
5256
private final MemorySegment stdoutHandle;
@@ -194,6 +198,18 @@ private void restore() {
194198
private static int readMode(Arena arena, MemorySegment handle) throws Throwable {
195199
MemorySegment slot = arena.allocate(4);
196200
if ((int) GET_CONSOLE_MODE.invokeExact(handle, slot) == 0) {
201+
// Under Git Bash / MSYS / MinTTY stdio is piped from the terminal
202+
// emulator rather than attached to a real Windows console, so
203+
// GetConsoleMode fails with ERROR_INVALID_HANDLE. Distinguish
204+
// that case so the user gets a pointer to `winpty` instead of
205+
// a bare "GetConsoleMode failed".
206+
int fileType = (int) GET_FILE_TYPE.invokeExact(handle);
207+
if (fileType == FILE_TYPE_PIPE) {
208+
throw new IOException(
209+
"TUI requires a real Windows console. Git Bash / MinTTY pipes stdio, so "
210+
+ "console APIs fail. Re-run via `winpty <command>` or switch to "
211+
+ "Windows Terminal, PowerShell, or cmd.exe.");
212+
}
197213
throw new IOException("GetConsoleMode failed");
198214
}
199215
return slot.get(ValueLayout.JAVA_INT, 0);

docs/how-to.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,23 @@ The `, stats` suffix on a row indicates the node carries zone-map statistics
125125
`vortex.dict` nodes show their dictionary entries; flat numeric leaves show
126126
a hex preview of the encoded buffer plus decoded data.
127127

128+
**Windows: Git Bash / MinTTY.** The TUI calls `GetConsoleMode` on stdio,
129+
which only works on a real Windows console handle. Git Bash and other
130+
MinTTY-based shells pipe stdio through the terminal emulator, so the
131+
console APIs fail and the TUI aborts with a `winpty` pointer in the error
132+
message. Two options:
133+
134+
```bash
135+
# wrap with winpty (ships with Git for Windows)
136+
winpty java -jar vortex-cli-*-all.jar tui data.vortex
137+
138+
# or switch to a terminal that attaches a real console: Windows Terminal,
139+
# PowerShell, or cmd.exe
140+
```
141+
142+
`inspect` (static, non-interactive) works in any shell since it does not
143+
toggle terminal modes.
144+
128145
---
129146

130147
## Project columns

0 commit comments

Comments
 (0)