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.
76
96%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
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:
<!-- 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.
<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:
// 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 filesc88db8e
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.