dotnet / dotnet/roslyn

Roslyn formatter silently corrupts tab/space indentation despite all formatting options disabled

Open
#83,285 13 comments 0 reactions 0 assignees View on GitHub
Area-IDE IDE-Formatter
Dominant language
C#
Stars
20.7k
Forks
4.3k
PR merge metrics
PR metrics pending

Description

# Roslyn formatter silently corrupts tab/space indentation despite all formatting options disabled

*Written up by Claude (Anthropic) based on information and code provided by Karl Botts.*

## Summary

Visual Studio 2026 (18.4.1+11612.150) (and 18.5.1 too) modifies tab/space indentation in source files without explicit user instruction, even after disabling every formatting-related option in Tools → Options and adding an `.editorconfig` file. The behavior is inconsistent — sometimes converting tabs to spaces, sometimes spaces with tabs — and affects lines the user has not touched. This forces a manual post-edit cleanup pass to undo the changes before committing to revision control.

This was also filed on Developer Community ([[link](https://developercommunity.visualstudio.com/t/Tab-sizes-are-not-working-again-in-VS/11050648)](https://developercommunity.visualstudio.com/t/Tab-sizes-are-not-working-again-in-VS/11050648)) with no response.

## Environment

- **IDE:** Visual Studio 2026, `installationName: VisualStudio/18.4.1+11612.150`
- **OS:** Windows
- **Primarily affected files:** `*.cs`, but other file types edited in VS are also affected
- **Project type:** C# / .NET

## Settings Already Disabled

The following have all been turned off in an attempt to stop this behavior. None of them fixed it:

- Tools → Options → Text Editor → All Languages → Tabs → **Keep Tabs**
- Tools → Options → Text Editor → C# → Tabs → **Keep Tabs**
- Tools → Options → Text Editor → Advanced → **Adaptive Formatting** (off)
- Tools → Options → Text Editor → Advanced → **Use adaptive formatting** (off)
- Code Cleanup profile — **Format Document** action removed
- `.editorconfig` at solution root containing:

```
root = true

[*]
indent_style = tab
```

None of these measures, individually or in combination, stop VS from silently altering whitespace.

## The Problem

When editing source files in VS 2026, the IDE silently modifies indentation on lines I have edited — and sometimes on lines I have **not** touched. The changes are inconsistent: sometimes tabs are replaced with spaces, sometimes spaces with tabs. The pattern does not correspond to any setting I can identify.

I only reliably detect these changes when I review diffs before committing to revision control, which is my standard practice. At that point I must manually identify and undo VS's alterations before committing, or commit whitespace noise that obscures the real changes.

I have been writing software professionally for over 40 years, including trading industry network systems where precision and consistency matter. I have never needed an automated script to undo my editor's unsolicited changes to my source files — until VS 2026.

## Evidence: A Cleanup Script I Should Not Need

The problem is consistent enough and frequent enough that I wrote a bash script, `fixVsMess`, to undo VS's changes after each editing session:

```bash
#!/bin/bash
# fixVsMess: Undoes whitespace corruption introduced by Visual Studio 2026.
# Runs each file through 'expand' then 'unexpand' to normalize tab/space usage
# to what it was before VS touched it.
# Requires files to be committed to revision control before use.

function EmitHelp() {
expand -t4 << __End_of_Help__
VisualStudio v18, aka 2026, does strange things to whitespace in source files,
and apparently nothing can be done to fix it.
This script fixes the resulting mess destructively, overwriting source code files.
It assumes you have everything committed to revision control before you use it.
For each filename arg, saves a verbatim backup with suffix ".bu",
runs the file through 'expand' to convert all tabs to spaces,
then through 'unexpand' to convert spaces back to tabs,
diffs the result against the backup to a file with suffix ".dff",
and removes the diff file only if it is empty.
With option -W, also trims trailing whitespace from lines.
__End_of_Help__
}

test "$1" == '--help' && { EmitHelp; exit; }

declare TrimTrailingWhitespaceFlag
while getopts 'W' Opt
do
case "$Opt" in
W) TrimTrailingWhitespaceFlag="1" ;;
*) echo "$0: see --help" 1>&2; exit 1 ;;
esac
done
shift $((OPTIND -1))

for Fn
do
declare BackupFn="$Fn.bu"
cp "$Fn" "$BackupFn"
expand -t4 "$BackupFn" | unexpand -t4 > "$Fn"
test "$TrimTrailingWhitespaceFlag" && sed -i -E 's/[[:space:]]+$//' "$Fn"
declare DiffFn="$Fn.dff"
diff -u "$BackupFn" "$Fn" > "$DiffFn"
if ! test -s "$DiffFn"; then rm "$DiffFn"; fi
done
```

The logic of this script illustrates the point: the correct behavior — expand tabs to spaces, then unexpand spaces back to tabs, consistently, at a defined tab stop — is **simple, well-established, and implemented in GNU coreutils tools that have been stable for decades**. `expand` and `unexpand` have behaved this way since before most current VS developers were born.

The fact that a workaround this simple is necessary reflects poorly on the complexity Roslyn has introduced into what should be a trivial, well-understood operation.

## What I Want

One thing: **do not modify anything I type, unless I have explicitly and immediately instructed you to do so.**

Not on save. Not on format. Not adaptively. Not as a side effect of Code Cleanup. Not on lines I haven't touched. Nothing. If VS cannot honor a "hands off my source" mode, then at minimum its behavior should be correct and consistent with decades of established practice — specifically, consistent with what `expand -t4 | unexpand -t4` produces.

## Questions for the Roslyn Team

1. Is there a combination of settings that actually achieves "never modify whitespace without explicit user action"? If so, what is it? The settings listed above do not achieve it.
2. Is silent modification of unedited lines a known bug?
3. Is the interaction between Adaptive Formatting, Code Cleanup, and language-specific formatting rules documented anywhere in a way that makes the effective combined behavior predictable?
4. Will VS 2026 receive a fix, or is this deferred to a future release?

## References

- Microsoft Learn: Configure indent and tab settings — https://learn.microsoft.com/en-us/visualstudio/ide/options-text-editor-all-languages-tabs
- Related Developer Community reports:
- [["Keep Tabs" setting not working in Visual Studio 2026](https://learn.microsoft.com/en-us/answers/questions/5648438/keep-tabs-setting-not-working-in-visual-studio-202)](https://learn.microsoft.com/en-us/answers/questions/5648438/keep-tabs-setting-not-working-in-visual-studio-202)
- [[Adaptive formatting doesn't respect Keep Tabs](https://developercommunity.visualstudio.com/t/11026483)](https://developercommunity.visualstudio.com/t/11026483)
- [[My own comment on the above, with no response](https://developercommunity.visualstudio.com/t/Tab-sizes-are-not-working-again-in-VS/11050648)](https://developercommunity.visualstudio.com/t/Tab-sizes-are-not-working-again-in-VS/11050648)

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.