Install any skill in seconds. Free to start, no credit card required.
Get Started Free →Guides authoring of MSBuild errors, warnings, and diagnostic messages. Consult when adding new MSBxxxx codes, writing or modifying user-facing diagnostic text, deciding between error/warning/message severity, working with Strings.resx resource files, formatting paths in error output, or evaluating whether a new warning could break WarnAsError builds.
.claude/skills/dotnet-authoring-errors-and-warnings/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-01 | ✗→✓ | ▲ Improved | 11% | 0% |
| case-02 | ✗→✓ | ▲ Improved | 52% | 0% |
| case-03 | ✗→✓ | ▲ Improved | -4% | 0% |
| case-05 | ✗→✓ | ▲ Improved | -33% | 0% |
| case-06 | ✗→✓ | ▲ Improved | 51% | 0% |
Error messages are MSBuild's primary user interface. They must help developers fix problems without reading source code.
For the mechanics of error code assignment, see assigning-msb-error-code.md.
Every error message must answer three questions:
xml<!-- BAD: What is "it"? What should I do? --> <value>MSB4999: Invalid configuration.</value> <!-- GOOD: States the problem, context, and fix --> <value>MSB4999: The project "{0}" specifies TargetFramework "{1}" which is not installed. Install the SDK for "{1}" or update the TargetFramework in the project file.</value>
Is the condition always wrong (invalid input, impossible state)?
├── Yes → ERROR (build should fail)
└── No
├── Could this cause subtle build correctness issues?
│ ├── Yes, likely → WARNING (but see WarnAsError impact below)
│ └── Yes, maybe → MESSAGE at Normal importance
└── Is this purely informational?
└── Yes → MESSAGE at Low importanceNew warnings are breaking changes for builds using:
-WarnAsError (CLI)<TreatWarningsAsErrors>true</TreatWarningsAsErrors> (project)<WarningsAsErrors>MSBxxxx</WarningsAsErrors> (specific codes)Before adding a new warning, consider:
| Range | Area | |-------|------| | MSB1xxx | Command-line handling | | MSB3xxx | Tasks (Microsoft.Build.Tasks.Core.dll) | | MSB4xxx | Engine (Microsoft.Build.dll) | | MSB5xxx | Shared code across assemblies | | MSB6xxx | Utilities (Microsoft.Build.Utilities) |
Strings.resx file for the appropriate assemblySee assigning-msb-error-code.md for detailed steps.
xml<data name="FeatureArea.DescriptiveName"> <value>MSBxxxx: Clear description with {0} placeholders for runtime values.</value> <comment>{StrBegin="MSBxxxx: "}{0} is the project file path. {1} is the property name.</comment> </data>
FeatureArea.DescriptiveName conventionMSBxxxx: (code, colon, space){StrBegin} marker and explains each {N} placeholderUse the standard formatting method that extracts and applies the error code:
csharp// For errors Log.LogErrorWithCodeFromResources("Copy.Error", sourceFile, destFile, ex.Message); // For warnings Log.LogWarningWithCodeFromResources("ResolveAssemblyReference.Conflict", assemblyName); // For engine-level errors (not in tasks) ProjectFileErrorUtilities.ThrowInvalidProjectFile( elementLocation, "InvalidProjectFile", arg1, arg2);
Never construct error messages by string concatenation — always use resource strings for localization support.
MSBxxxx) are never localized.xlf placeholder translations<comment> elements to help translators understand contextIElementLocation when available — this enables IDE click-to-navigateStrings.resx range{StrBegin} comment and placeholder documentation added.xlf files| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-01 | fail→pass | 13,951 | 14,123 | +1% | 1 | 1 | 0% | 2,351 | 2,621 | +11% | 0 | 0 | — |
case-02 | fail→pass | 12,231 | 11,170 | -9% | 1 | 1 | 0% | 1,966 | 2,981 | +52% | 0 | 0 | — |
case-03 | fail→pass | 22,374 | 14,038 | -37% | 1 | 1 | 0% | 3,913 | 3,756 | -4% | 0 | 0 | — |
case-04 | pass→pass | 9,006 | 2,935 | -67% | 1 | 1 | 0% | 1,533 | 1,761 | +15% | 0 | 0 | — |
case-05 | fail→pass | 15,902 | 2,521 | -84% | 1 | 1 | 0% | 2,485 | 1,656 | -33% | 0 | 0 | — |
case-06 | fail→pass | 21,954 | 2,712 | -88% | 1 | 1 | 0% | 1,134 | 1,718 | +51% | 0 | 0 | — |
case-07 | fail→pass | 16,980 | 3,215 | -81% | 1 | 1 | 0% | 1,071 | 1,807 | +69% | 0 | 0 | — |
case-08 | pass→pass | 7,635 | 2,861 | -63% | 1 | 1 | 0% | 1,215 | 1,740 | +43% | 0 | 0 | — |
case-09 | fail→pass | 24,061 | 4,608 | -81% | 1 | 1 | 0% | 1,804 | 2,024 | +12% | 0 | 0 | — |
case-10 | fail→pass | 14,560 | 2,420 | -83% | 1 | 1 | 0% | 2,105 | 1,673 | -21% | 0 | 0 | — |
case-11 | fail→pass | 11,172 | 2,822 | -75% | 1 | 1 | 0% | 1,401 | 1,746 | +25% | 0 | 0 | — |
case-12 | fail→pass | 8,391 | 3,579 | -57% | 1 | 1 | 0% | 1,244 | 1,913 | +54% | 0 | 0 | — |
case-22 | pass→pass | 12,863 | 12,168 | -5% | 1 | 1 | 0% | 2,369 | 3,671 | +55% | 0 | 0 | — |
case-13 | fail→pass | 6,523 | 3,080 | -53% | 1 | 1 | 0% | 1,145 | 1,815 | +59% | 0 | 0 | — |
case-14 | fail→pass | 13,328 | 5,428 | -59% | 1 | 1 | 0% | 2,157 | 2,197 | +2% | 0 | 0 | — |
case-15 | fail→pass | 13,967 | 2,987 | -79% | 1 | 1 | 0% | 2,270 | 1,777 | -22% | 0 | 0 | — |
case-16 | fail→pass | 20,304 | 3,553 | -83% | 1 | 1 | 0% | 2,823 | 1,675 | -41% | 0 | 0 | — |
case-23 | pass→pass | 12,722 | 11,974 | -6% | 1 | 1 | 0% | 2,456 | 3,472 | +41% | 0 | 0 | — |
case-17 | pass→pass | 11,658 | 3,886 | -67% | 1 | 1 | 0% | 2,010 | 1,905 | -5% | 0 | 0 | — |
case-18 | pass→pass | 12,502 | 3,852 | -69% | 1 | 1 | 0% | 1,778 | 1,883 | +6% | 0 | 0 | — |
case-19 | pass→pass | 11,215 | 8,449 | -25% | 1 | 1 | 0% | 1,625 | 1,896 | +17% | 0 | 0 | — |
case-20 | fail→pass | 8,641 | 2,493 | -71% | 1 | 1 | 0% | 1,467 | 1,683 | +15% | 0 | 0 | — |
case-21 | pass→pass | 11,582 | 13,714 | +18% | 1 | 1 | 0% | 2,132 | 3,763 | +77% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 23 cases were attempted, and 21 counted toward the lift figure. The other 2 produced results that are not comparable between the two arms, so they are excluded from the headline rather than averaged into it. The headline lift of +65 percentage points is the difference between those two pass rates over the 21 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.