Skip to content

data ingest: arrow keys do not navigate the guided prompts on Windows (ENABLE_VIRTUAL_TERMINAL_INPUT breaks survey's VK_UP/VK_DOWN path) #475

Description

@shujaatTracebloc

What happens

On Windows, arrow keys stop navigating the guided prompts. In the tb data ingest task-type
Select, pressing the down arrow prints [B into the filter line and the highlighted option
never moves, so the list cannot be navigated at all:

? Which task type?  [Use arrows to move, type to filter]
? [B[B

Enter then either selects the wrong (still-default) option or fails the filter.

Why

survey's Windows rune reader (terminal/runereader_windows.go) reads console records with
ReadConsoleInputW and recognises navigation from the virtual key codes VK_UP / VK_DOWN.
Before reading it clears ENABLE_ECHO_INPUT, ENABLE_LINE_INPUT and ENABLE_PROCESSED_INPUT
but not ENABLE_VIRTUAL_TERMINAL_INPUT.

When that flag is set on the console, Windows stops delivering arrows as VK_* key events and
delivers them as ANSI escape sequences (ESC [ B) instead. survey sees three ordinary
runes: the ESC is dropped and [B lands in the filter. No VK_DOWN ever arrives, so
navigation cannot fire.

This is why it can regress with no change on our side: console input mode is state on the
console handle, not something the CLI selects. A terminal that opts into virtual-terminal input,
or any program in the session that sets the flag and does not restore it, flips the behaviour.

survey/v2 v2.3.7 is the newest release, so there is no upstream version to bump to.

Fix

Clear ENABLE_VIRTUAL_TERMINAL_INPUT on stdin for the duration of each prompt and restore the
caller's original mode afterwards, so survey's key-event path works regardless of what turned
the flag on. No-op off Windows (POSIX uses raw mode, where survey parses the escape sequences
itself and arrows already work), and a no-op when stdin is not a console — the helper must never
be able to break a run.

Workaround until released

Skip the prompts entirely:

tb data ingest "<path>" --name <name> --task <task> --intent train --no-input

Or type to filter (e.g. masked) instead of using arrows.

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions