C# Using Directives: IDE0055 Format Violations Don't Always Trigger as Expected

Update (February 2026): This issue has been resolved. The Roslyn team merged PR #81202 on November 13, 2025, which fixes IDE0055 to enforce dotnet_separate_import_directive_groups based on grouping (contiguity) rather than alphabetical sorting. The fix shipped after the .NET 10.0 GA release (November 11, 2025) and is expected to be available in .NET 10 servicing updates (SDK 10.0.1xx+). See the Resolution section below for details.

Many C# teams rely on analyzer rule IDE0055 to enforce consistent code formatting across their projects. It's one of the standard tools in the .editorconfig-driven approach to code style, and for most formatting concerns, it works as expected. However, I discovered an undocumented interaction between IDE0055 and the dotnet_separate_import_directive_groups option that caused the rule to silently skip violations under specific conditions. This post documents the issue, the root cause in the Roslyn source, the real-world consequences, and the eventual fix.

The Unexpected Behavior

While configuring formatting rules for a project, I noticed that IDE0055 wasn't flagging certain files where using directives lacked the required group separators. After investigation, I reported the issue to the Roslyn team.

What I found was this: IDE0055 only enforced the separation of using directive groups when those directives were already in alphabetical order. If the directives were out of alphabetical order, even if they were properly grouped by namespace, no violation was reported.

The following two examples illustrate the discrepancy.

Example 1: Alphabetically Sorted Directives (Triggers IDE0055)

namespace MyNamespace;

using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using NuGet.Versioning;
using System.Diagnostics;

With dotnet_separate_import_directive_groups = true in .editorconfig, the analyzer correctly flags this code because the Azure, NuGet, and System groups should be separated by blank lines.

Example 2: Non-Alphabetically Sorted Directives (No IDE0055 Violation)

namespace MyNamespace;

using Azure.Storage.Blobs;
using Azure.Storage.Sas;
using System.Diagnostics;
using NuGet.Versioning;

This code has the same formatting problem (unseparated groups) but doesn't trigger a violation. The only difference is that System.Diagnostics and NuGet.Versioning aren't in alphabetical order.

Root Cause (Prior to the Fix)

I traced the cause to the TokenBasedFormattingRule.AdjustNewLinesAfterSemicolonToken() method in the Roslyn source. The relevant code path contained this conditional check:

if (usings.IsSorted(UsingsAndExternAliasesDirectiveComparer.SystemFirstInstance) ||
    usings.IsSorted(UsingsAndExternAliasesDirectiveComparer.NormalInstance))
{
    // Only apply the formatting rule if usings are sorted
    // ...
}

The formatting rule intentionally verified that the using directives were already sorted before enforcing group separation. A comment in the Roslyn source confirmed this was deliberate:

"if the user is separating using-groups, and we're between two usings, and these usings should be separated, then do so (if the usings were already properly sorted)."

The original intent was presumably to avoid inserting separators into a disordered list of usings, where group boundaries would be ambiguous. In practice, however, this created a silent gap in enforcement.

The Documentation Gap

None of this behavior was documented. The official documentation for dotnet_separate_import_directive_groups made no mention of a prerequisite that using directives must be alphabetically sorted for the rule to take effect. The option appeared to be unconditional, and developers configured it with that expectation.

Impact and Implications

The hidden dependency on sorting order produced several concrete problems:

  1. Inconsistent enforcement. The same logical violation (missing group separators) would be reported in one file and silently ignored in another, depending on an unrelated property of the code (alphabetical order).

  2. Silent non-compliance. Files that appeared to conform to the team's coding standard actually violated it, with no analyzer warning to surface the discrepancy. Over time, this led to codebase inconsistency that was difficult to detect through automated tooling.

  3. Misleading configuration. Developers reasonably believed that enabling the option was sufficient to enforce group separation. The absence of warnings on certain files reinforced the false impression that those files were already compliant.

Real-World Impact Scenarios

While this may appear to be a narrow formatting concern, its effects propagated through several common development workflows.

Enforcing Corporate Coding Standards

Organizations that rely on automated analysis to enforce coding standards had a gap in their validation pipeline. Code that appeared compliant could pass all automated checks while actually violating the intended standard, undermining confidence in the tooling.

Code Review Inconsistencies and Team Onboarding

When the same logical issue triggers violations in some files but not others, code reviews become unpredictable. Reviewers may enforce standards inconsistently, and new team members struggle to understand why identical patterns are flagged in one context and ignored in another. This erodes trust in the development process and increases onboarding friction.

Build Server Validation

Teams that configure their builds to fail on style violations encountered a frustrating asymmetry: builds might pass locally but fail on the build server, or vice versa, depending on the ordering of usings in the files being checked and which tools were performing the validation.

Legacy Code Migration

When migrating legacy codebases to modern formatting standards, teams depend on automated tooling to identify every instance of non-compliance. If some violations are invisible to the analyzer, pockets of legacy formatting persist through the migration, creating long-lived technical debt that requires manual intervention to discover and correct.

Cross-Project Consistency

In solutions with multiple projects sharing developers and code, the inconsistent enforcement led to subtle formatting divergence across projects. Developers moving between projects encountered different formatting patterns despite identical .editorconfig configurations, making code navigation and maintenance more difficult than necessary.

The Core Issue

What made this problem particularly stubborn was that the standard remediation approaches didn't address it:

  1. Combining rules didn't help. Configuring both dotnet_sort_system_directives_first and dotnet_separate_import_directive_groups still left the issue in place. The sorting rule ordered System namespaces before others, but without full alphabetical order within each group, the separation rule remained inactive.

  2. Code Cleanup didn't fix it. Visual Studio's Code Cleanup feature operates only on triggered violations. Since the rule never triggered for non-sorted usings, Code Cleanup had nothing to act on.

  3. Format Document didn't catch it. The Format Document command similarly relied on the rule firing, and in the absence of a violation, it left the non-compliant formatting untouched.

Working Around the Issue

Note: On a .NET SDK version that includes the fix (see Resolution below), these workarounds are no longer necessary. Updating the SDK is the recommended solution.

For teams still on older SDK versions, the following approaches mitigate the problem:

1. Update the .NET SDK

The most effective resolution is to update to a .NET SDK version that includes the Roslyn fix from PR #81202. The fix was merged on November 13, 2025, and is expected in .NET 10 servicing updates (SDK 10.0.1xx+).

2. Manual Inspection

If updating isn't feasible, manual review remains the only reliable way to identify this specific formatting issue. Teams can also develop custom scripts or tooling to scan for unseparated using groups.

3. Custom Roslyn Analyzer

A custom Roslyn analyzer that checks for using directive grouping regardless of sorting order provides a permanent solution for older target frameworks. This requires development effort, but the analyzer can be packaged as a NuGet package and shared across the organization.

4. Documentation and Team Awareness

Ensuring that the team understands this quirk reduces confusion during code reviews and prevents wasted time investigating why the analyzer doesn't flag certain files.

5. Comprehensive EditorConfig

While a comprehensive .editorconfig doesn't fully solve the issue on older SDKs, it minimizes the window of opportunity for non-compliance when combined with deliberate formatting practices:

# .editorconfig
# Enforce using directive sorting and grouping
dotnet_sort_system_directives_first = true
dotnet_separate_import_directive_groups = true

# Make the rule an error to catch it during build
dotnet_diagnostic.IDE0055.severity = error

# Other related formatting options
csharp_using_directive_placement = outside_namespace

The strategy is to ensure usings are properly sorted first, through manual formatting or automated tools, so that IDE0055 can then effectively enforce grouping. With the fix applied, this .editorconfig configuration works as originally expected without the sorting prerequisite.

Affected Tools and Automation

This issue affected a broad range of tools and automation systems that rely on .editorconfig and Roslyn analyzers to enforce code standards.

CI/CD Pipeline Tools

These systems could inconsistently enforce standards, allowing builds to pass that should have failed or producing failures that were difficult to reproduce locally.

Code Analysis Tools

Different analysis tools could report conflicting results depending on how they interpreted and applied the underlying rules.

Git Hooks and Pre-Commit Validation

These systems could fail to catch formatting issues that should have been corrected before committing.

IDE Extensions and Plugins

IDE plugins could apply inconsistent fixes or fail to identify violations, creating a disconnect between what developers saw locally and what the CI pipeline enforced.

The inconsistency of IDE0055's behavior meant that none of these tools could reliably enforce the intended standard, undermining automated code quality workflows throughout the development lifecycle.

Technical Explanation

The root cause was a hidden dependency in IDE0055's implementation of dotnet_separate_import_directive_groups. The UsingsAndExternAliasesOrganizer.NeedsGrouping() method correctly determined when two namespaces should belong to different groups based on their first token. However, the actual enforcement of group separation was gated behind a check that the using directives were already sorted in one of two orders:

  1. Full alphabetical order, or
  2. System namespaces first, followed by other namespaces in alphabetical order

This implementation detail contradicted the documented behavior of both dotnet_separate_import_directive_groups and dotnet_sort_system_directives_first, creating a gap between what the documentation promised and what the tooling delivered.

Resolution

On November 13, 2025, the Roslyn team merged PR #81202, resolving the issue. The fix was reviewed and merged by Cyrus Najmabadi (a Roslyn team contributor) and approved by Joe Robich (a Roslyn team member).

What Changed

The fix changed how IDE0055 decides whether to enforce group separation:

The old sorting check in TokenBasedFormattingRule.cs:

if (usings.IsSorted(UsingsAndExternAliasesDirectiveComparer.SystemFirstInstance) ||
    usings.IsSorted(UsingsAndExternAliasesDirectiveComparer.NormalInstance))

Was replaced with a new AreUsingsProperlyGrouped() method that checks contiguity, verifying that all usings with the same first namespace token appear together, without requiring any particular order between groups.

The New Behavior

With the fix applied, Example 2 from above now correctly triggers an IDE0055 violation, because the Azure, System, and NuGet groups are contiguous even though they aren't alphabetically sorted. The only scenario where separators aren't enforced is when usings of the same namespace group are genuinely scattered. For example, Azure usings at both the beginning and end of the list with other namespaces in between, since the grouping boundaries would be ambiguous in that case.

Availability

The fix was merged to Roslyn's main branch on November 13, 2025, two days after the .NET 10.0 GA release (November 11, 2025). It's expected to be available in .NET 10 servicing SDK updates (10.0.1xx+). Users on .NET 9 or earlier will need to upgrade to a .NET 10+ SDK to benefit from this fix.

Conclusion

This article documented an undocumented behavior in IDE0055's handling of using directive formatting, a gap between the expected and actual functionality of a widely used code analysis rule. The issue report led to a productive discussion with the Roslyn team, and the bug was ultimately fixed in PR #81202, which shifted the enforcement logic from requiring alphabetical sorting to requiring contiguous grouping.

For teams still on older SDK versions, the workarounds described above remain relevant. For everyone else, updating to a .NET SDK that includes the fix is the straightforward path forward.

Note: The original behavior described in this article was verified with .NET SDK version 9.0.201 and Visual Studio 2022 (17.13.5). The fix was merged into Roslyn on November 13, 2025 and is expected in .NET 10 servicing SDK updates. To confirm a given SDK includes the fix, test it with non-sorted but contiguous using directives.

References