dotnet / dotnet/msbuild

Build verbosity changes depending on whether stdout is a terminal or a pipe

Open
#13,852 2 comments 1 reaction 1 assignee Claimed by @baronfel View on GitHub
Area: Terminal Logger triaged
Dominant language
C#
Stars
5.5k
Forks
1.5k
Avg merge
1d 8h
Merged PRs (30d)
141

Description

### Problem

Running `dotnet build` interactively and running `dotnet build > log.txt` produce different output — not just in formatting, but in **content**. Messages that appear in the log file are completely absent from the interactive terminal, even at the same verbosity level.

This happens because interactive sessions use the terminal logger (default since .NET 9), while piped output falls back to the console logger. The two loggers apply different rules for which messages they display.

I understand this is by design with the terminal logger, but I believe it's a mistake — the effective verbosity of a build should not change based on where stdout is going.

### Impact on AI-assisted development

AI coding agents like GitHub Copilot interact with MSBuild by capturing stdout, so they always get the console logger. When an agent helps a developer write build targets or MSBuild plugins, it sees high-importance messages in its captured output and assumes the developer will see them too. But the developer, running interactively with the terminal logger, won't.

This means the agent and the developer are looking at different views of the same build without either side knowing it. As AI-assisted development becomes more common, this divergence becomes increasingly problematic — agents can't reliably reason about what the developer will actually see.

### Reproduction

Add a high-importance message to any project:

```xml

```

- `dotnet build` interactively → message is hidden
- `dotnet build > log.txt` → message appears in the file

### This breaks convention

Console tools routinely adjust *formatting* when piping — stripping colors, disabling progress bars, removing interactive elements. But they generally don't change *verbosity*. Users expect to see the same information whether they're watching the output live or capturing it.

`MessageImportance.High` is the documented contract for communicating with users. Targets, tasks, and plugins use it to surface information the user is expected to see. The terminal logger silently breaks this contract, leaving authors with no good way to reliably show a message to the user.

### Verbosity gap

The console logger shows `MessageImportance.High` messages at `minimal` verbosity and above. The terminal logger requires `detailed` — two levels higher.

| Verbosity | Piped to file | Interactive terminal |
|-----------|--------------|---------------------|
| `quiet` | ❌ | ❌ |
| `minimal` | ✅ | ❌ |
| `normal` | ✅ | ❌ |
| `detailed`| ✅ | ✅ |

### Workarounds (all unsatisfying)

- `/tl:false` — gives up the terminal logger entirely
- `/tlp:verbosity=detailed` — currently the best workaround, but requires every user/CI script to know about it; it should not be necessary for `MessageImportance.High` messages
- `LogWarning` — always visible, but semantically incorrect, repeated in the build summary, and inflates warning counts

### Suggestion

The terminal logger should display `MessageImportance.High` messages at the same verbosity levels as the console logger. Piping to a file should change formatting and interactivity — not what information is shown.

---

*This content was created with assistance from AI.*

Contributor guide

No contributing guide indexed for this repository

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.