Summary
Reject path inputs whose entire value consists only of whitespace (string.IsNullOrWhiteSpace(value) is true). Apply this consistently on Windows, Linux, and macOS.
Motivation
Supporting path names that consist only of whitespace does not provide a meaningful MSBuild scenario, but preserving that behavior creates compatibility and correctness risks for path absolutization.
Windows path APIs may reject or normalize whitespace-only values, while Unix can preserve them as legal path segments. This platform difference complicates path handling and makes multithreaded task migrations easier to get wrong. A whitespace-only property, item identity, or metadata value can also be unintentionally resolved relative to the project directory and then have its whitespace trimmed instead of being reported as invalid input.
Proposed implementation
Central validation in AbsolutePath
Add a wave-gated string.IsNullOrWhiteSpace(path) check in the AbsolutePath constructor. Add a localized Framework exception message and throw ArgumentException.
The constructor receives only the path value and base path. It does not receive the originating task parameter, item, property, or metadata name, so its exception is the generic fallback when no higher-level caller supplies that context.
Contextual diagnostics at built-in task call sites
When a built-in task calls TaskEnvironment.GetAbsolutePath, the task code knows which of its inputs it is processing. For example, at a call such as TaskEnvironment.GetAbsolutePath(SourceFiles[i].ItemSpec), the task can validate the value before the call and log an error containing nameof(SourceFiles), the item value, and the item index.
This contextual diagnostic is possible, but it requires updating each relevant task call site. The existing TaskEnvironment.GetAbsolutePath(string) API receives only the path string and cannot infer the task property or item name automatically.
Contextual diagnostics for typed path parameters
PR #13971 implements typed task parameters and items. When a task author changes an input type from string or ITaskItem to AbsolutePath, FileInfo, or DirectoryInfo, parameter binding routes the value through TaskExecutionHost.
TaskExecutionHost calls TaskEnvironment.GetAbsolutePath, the central AbsolutePath validation throws ArgumentException for whitespace-only values, and the existing parameter-binding error handling converts that exception into a user-friendly error containing the value, task parameter name, declared type, task name, and project location.
Legacy tasks that call TaskEnvironment.GetAbsolutePath but do not add task-level validation receive the generic AbsolutePath fallback error. Tasks that neither use typed path parameters nor resolve their values through TaskEnvironment.GetAbsolutePath cannot be identified generically as path consumers and will retain their existing behavior.
Change Wave
Gate behavior changes to existing path consumers with ChangeWaves.Wave18_10. Setting MSBUILDDISABLEFEATURESFROMVERSION=18.10 preserves the previous behavior until the wave rotates out.
Summary
Reject path inputs whose entire value consists only of whitespace (
string.IsNullOrWhiteSpace(value)istrue). Apply this consistently on Windows, Linux, and macOS.Motivation
Supporting path names that consist only of whitespace does not provide a meaningful MSBuild scenario, but preserving that behavior creates compatibility and correctness risks for path absolutization.
Windows path APIs may reject or normalize whitespace-only values, while Unix can preserve them as legal path segments. This platform difference complicates path handling and makes multithreaded task migrations easier to get wrong. A whitespace-only property, item identity, or metadata value can also be unintentionally resolved relative to the project directory and then have its whitespace trimmed instead of being reported as invalid input.
Proposed implementation
Central validation in
AbsolutePathAdd a wave-gated
string.IsNullOrWhiteSpace(path)check in theAbsolutePathconstructor. Add a localized Framework exception message and throwArgumentException.The constructor receives only the path value and base path. It does not receive the originating task parameter, item, property, or metadata name, so its exception is the generic fallback when no higher-level caller supplies that context.
Contextual diagnostics at built-in task call sites
When a built-in task calls
TaskEnvironment.GetAbsolutePath, the task code knows which of its inputs it is processing. For example, at a call such asTaskEnvironment.GetAbsolutePath(SourceFiles[i].ItemSpec), the task can validate the value before the call and log an error containingnameof(SourceFiles), the item value, and the item index.This contextual diagnostic is possible, but it requires updating each relevant task call site. The existing
TaskEnvironment.GetAbsolutePath(string)API receives only the path string and cannot infer the task property or item name automatically.Contextual diagnostics for typed path parameters
PR #13971 implements typed task parameters and items. When a task author changes an input type from
stringorITaskItemtoAbsolutePath,FileInfo, orDirectoryInfo, parameter binding routes the value throughTaskExecutionHost.TaskExecutionHostcallsTaskEnvironment.GetAbsolutePath, the centralAbsolutePathvalidation throwsArgumentExceptionfor whitespace-only values, and the existing parameter-binding error handling converts that exception into a user-friendly error containing the value, task parameter name, declared type, task name, and project location.Legacy tasks that call
TaskEnvironment.GetAbsolutePathbut do not add task-level validation receive the genericAbsolutePathfallback error. Tasks that neither use typed path parameters nor resolve their values throughTaskEnvironment.GetAbsolutePathcannot be identified generically as path consumers and will retain their existing behavior.Change Wave
Gate behavior changes to existing path consumers with
ChangeWaves.Wave18_10. SettingMSBUILDDISABLEFEATURESFROMVERSION=18.10preserves the previous behavior until the wave rotates out.