Azure / Azure/azure-functions-core-tools
Prompts crash with unexpected error when stdout or stderr is redirected
- Dominant language
- C#
- Stars
- 1.5k
- Forks
- 498
- Avg merge
- 5d 4h
- Merged PRs (30d)
- 15
Description
## Problem
`IInteractionService.IsInteractive` is wired to Spectre's `Capabilities.Interactive`, which tracks stdin. The prompts it guards need ANSI on the **output** stream. Redirect either output stream and the guard still reports interactive, so the prompt runs and Spectre throws.
```csharp
public bool IsInteractive => AnsiConsole.Profile.Capabilities.Interactive;
```
The throw lands in `Program.Main`'s last-resort `catch (Exception)`, so the user gets "An unexpected error occurred", telemetry records a failure, and the guidance the command meant to print never appears.
## Repro
Node project with templates installed.
```
$ func new > out.txt 2>&1
Error: An unexpected error occurred: Cannot show selection prompt since the
current terminal does not support ANSI escape sequences.
exit 1
$ func init > out.txt 2>&1
Error: An unexpected error occurred: Cannot show selection prompt since the
current terminal does not support ANSI escape sequences.
exit 1
```
Redirection matrix for `func new` with no `--template`
| redirected | result |
| --- | --- |
| stdout only | crash |
| stderr only | crash |
| stdout and stderr | crash |
| stdin only | correct message, "Missing required option: --template" |
Only the stdin case behaves, and stdin is the one thing `Capabilities.Interactive` actually tracks.
## Expected
Redirecting output should take the same path as non-interactive. `func new` prints "Missing required option: --template", `func init` says which options it needs.
## Fix
In `src/Func/Console/SpectreInteractionService.cs`
- gate prompts on the ANSI capability of the console being written to, not `AnsiConsole.Profile.Capabilities.Interactive`
- note `IsInteractive` reads the static stdout profile while prompts render to a separately constructed `_stderr` console, so the two can disagree. Check the console the prompt actually uses.
- add a test per prompt method covering the redirected case
Affects `ConfirmAsync`, `PromptForSelectionAsync`, `PromptForMultiSelectionAsync` and the text prompt, so `func new`, `func init` and anything else that prompts.
## Notes
This is common in CI, with `tee`, and in any script that captures output while stdin stays attached.
Found while reviewing #5448, unrelated to that change.
Contributor guide
Assessment
This issue has not been assessed yet.