Azure / Azure/azure-functions-core-tools

Prompts crash with unexpected error when stdout or stderr is redirected

Closed
#5,511 0 comments 0 reactions 1 assignee Claimed by @ahmedmuhsin View on GitHub
bug v5
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.