.slnx is the modern XML-based solution format introduced by Microsoft β and honestly, it's a great improvement over the old .sln format. It's human-readable, merge-friendly, and easy to edit by hand. π
There's just one catch: neither Visual Studio, MSBuild, nor the dotnet CLI fully validates .slnx files. Invalid constructs are silently accepted, which can lead to confusing errors that are surprisingly hard to trace back to the solution file.
slnx-validator fills that gap. It catches the issues the toolchain quietly ignores. π
You could read more about the .slnx at the official .NET blog post
dotnet tool install -g slnx-validatorslnx-validator runs on .NET 8, 9, and 10. Note that using .slnx files in your projects requires .NET SDK 9 or later β but your projects themselves can still target .NET 8.
Validate a single file:
slnx-validator MySolution.slnxValidate all .slnx files in a folder:
slnx-validator src\Validate using a wildcard pattern:
slnx-validator src\MyProject*.slnxValidate multiple files, folders, or patterns at once (comma-separated):
slnx-validator "MySolution.slnx, src\*.slnx, other\"Exit code 0 means everything is valid. Exit code 1 means one or more errors were found.
Writes a SonarQube generic issue report to the specified JSON file. Import it into your Sonar analysis via the sonar.externalIssuesReportPaths property.
π‘ When using
--sonarqube-report-file, it's recommended to also pass--continue-on-errorso the tool always exits with code0. This lets the SonarQube quality gate β not the tool's exit code β determine whether your pipeline fails.
slnx-validator MySolution.slnx --sonarqube-report-file sonar-issues.json --continue-on-errorAlways exits with code 0, even when validation errors are found. Useful in CI pipelines where SonarQube handles the failure decision. Default: false.
Verify that a set of files or directories matching glob patterns exist on disk and are referenced as <File> entries in the solution file(s) being validated. Any failure is reported as a normal validation error (exit code 1) that also appears in SonarQube reports.
- Disk check β if no files match the glob patterns, a
SLNX020(RequiredFileDoesntExistOnSystem) error is added to the solution result. - Reference check β for each matched file that is not referenced as
<File Path="...">in the.slnx, aSLNX021(RequiredFileNotReferencedInSolution) error is added. The error message shows the exact<File>element that should be added.
Relative paths in the .slnx are resolved relative to the solution file's location.
Syntax
--required-files "<pattern1>;<pattern2>;..."
Patterns are separated by ;. Patterns starting with ! are exclusions. Pattern order matters: a later pattern can override an earlier one.
Supported glob syntax
| Pattern | Meaning | Example |
|---|---|---|
* |
Any file in the current directory (no path separator) | doc/*.md |
** |
Any depth of subdirectories | src/**/*.cs |
!pattern |
Exclude matching paths | !**/bin/** |
dir/ |
Match a directory and its contents | docs/ |
Note:
{a,b}alternation and[abc]character classes are not supported by this library. Use multiple patterns separated by;instead. For example, instead of*.{cs,fs}, use**/*.cs;**/*.fs.
Examples
Require all .md files under doc/:
slnx-validator MySolution.slnx --required-files "doc/*.md"
Require all .yaml files except those in the src/ folder:
slnx-validator MySolution.slnx --required-files "**/*.yaml;!src/**"
Require a specific config file and the entire docs/ directory:
slnx-validator MySolution.slnx --required-files "appsettings.json;docs/"
Exit codes
| Code | Description |
|---|---|
0 |
All patterns matched and all matched files are referenced in the solution. |
1 |
Any validation error β including required files not existing or not referenced. |
slnx-validator MySolution.slnx --sonarqube-report-file sonar-issues.json --continue-on-error{
"rules": [
{
"id": "SLNX011",
"name": "Referenced file not found",
"description": "A file referenced in a <File Path=\"...\"> element does not exist on disk.",
"engineId": "slnx-validator",
"cleanCodeAttribute": "COMPLETE",
"type": "BUG",
"severity": "MAJOR",
"impacts": [
{
"softwareQuality": "MAINTAINABILITY",
"severity": "HIGH"
}
]
}
],
"issues": [
{
"ruleId": "SLNX011",
"primaryLocation": {
"message": "File not found: docs\\CONTRIBUTING.md",
"filePath": "MySolution.slnx",
"textRange": {
"startLine": 4
}
}
}
]
}Then configure the SonarQube scanner:
sonar.externalIssuesReportPaths=sonar-issues.jsonslnx-validator MySolution.slnx[OK] MySolution.slnx
slnx-validator MySolution.slnx[FAIL] MySolution.slnx
MySolution.slnx
- line 5: [SLNX013] The element 'Folder' in namespace '...' has invalid child element 'Folder'. List of possible elements expected: 'Project'.
- line 12: [SLNX011] File not found: docs\CONTRIBUTING.md
slnx-validator src\[OK] src\Frontend.slnx
[FAIL] src\Backend.slnx
src\Backend.slnx
- line 4: [SLNX011] File not found: docs\CONTRIBUTING.md
- line 8: [SLNX012] Wildcard patterns are not supported in file paths: docs\*.md
This tool checks what dotnet / MSBuild / Visual Studio does not validate by default:
-
XSD schema validation β verifies that the
.slnxfile conforms to the official Microsoft schema. Visual Studio silently accepts certain invalid constructs without showing any error β for example, a<Folder>nested inside another<Folder>(seeexamples/invalid-xsd.slnx). -
Solution folder file existence β checks that every
<File Path="...">listed inside a<Folder>actually exists on disk. -
Wildcard usage β
.slnxdoes not support wildcard patterns. Visual Studio silently accepts them but simply ignores the entries, so your files appear to be listed but are never actually resolved.slnx-validatorcatches this in<File Path="...">entries (seeexamples/invalid-wildcard.slnx):<!-- β Silently ignored by Visual Studio β no error, no files loaded --> <Folder Name="docs"> <File Path="docs\*.md" /> </Folder>
Wildcard support is a known open request that was closed as not planned.
The following are intentionally out of scope because the toolchain already handles them:
- Project file existence (
<Project Path="...">) βdotnet build/ MSBuild already reports missing project files.
| Code | Name | Description |
|---|---|---|
SLNX001 |
FileNotFound |
The input .slnx file does not exist. |
SLNX002 |
InvalidExtension |
The input file does not have a .slnx extension. |
SLNX003 |
NotATextFile |
The file is binary and cannot be parsed as XML. |
SLNX010 |
InvalidXml |
The file is not valid XML (see examples/invalid-not-xml.slnx). |
SLNX011 |
ReferencedFileNotFound |
A file referenced in <File Path="..."> does not exist on disk. |
SLNX012 |
InvalidWildcardUsage |
A <File Path="..."> contains a wildcard pattern (see examples/invalid-wildcard.slnx). |
SLNX013 |
XsdViolation |
The XML structure violates the schema, e.g. <Folder> inside <Folder> (see examples/invalid-xsd.slnx). |
SLNX020 |
RequiredFileDoesntExistOnSystem |
A --required-files pattern matched no files on the file system. |
SLNX021 |
RequiredFileNotReferencedInSolution |
A --required-files matched file exists on disk but is not referenced as a <File> element in the solution. |
Microsoft doesn't provide much documentation for the .slnx format, but there is an XSD schema in the official vs-solutionpersistence repository β and it's enough to catch real structural problems before they cause trouble:
Licensed under the MIT License β Copyright (c) Microsoft Corporation.