Type of issue
Code doesn't work
Description
The "Add subcommands and custom validation" section places file-existence validation inside DefaultValueFactory:
Option<FileInfo> fileOption = new("--file")
{
Description = "An option whose argument is parsed as a FileInfo",
Required = true,
DefaultValueFactory = result =>
{
if (result.Tokens.Count == 0)
{
return new FileInfo("sampleQuotes.txt");
}
string filePath = result.Tokens.Single().Value;
if (!File.Exists(filePath))
{
result.AddError("File does not exist");
return null;
}
else
{
return new FileInfo(filePath);
}
}
};
The article states:
"Without this code, missing files are reported with an exception and stack trace. With this code just the specified error message is displayed."
This doesn't work. DefaultValueFactory only runs when no value is provided for the option. When a user passes --file nofile, System.CommandLine's built-in parser converts the argument directly to FileInfo (which doesn't validate existence), bypassing DefaultValueFactory entirely. The action handler then throws a FileNotFoundException with a stack trace.
Suggested fix (option A — built-in validator):
fileOption.AcceptExistingOnly();
Suggested fix (option B — custom validator with custom error message):
fileOption.Validators.Add(result =>
{
var file = result.GetValueOrDefault<FileInfo>();
if (file is not null && !file.Exists)
{
result.AddError("File does not exist");
}
});
In both cases, DefaultValueFactory should be simplified to only handle the default:
DefaultValueFactory = result =>
{
if (result.Tokens.Count == 0)
{
return new FileInfo("sampleQuotes.txt");
}
return new FileInfo(result.Tokens.Single().Value);
}
References:
AcceptExistingOnly() extension method validates that a FileInfo, DirectoryInfo, or FileSystemInfo path exists before the action handler runs:
Validators.Add() for custom validation beyond file existence (e.g., range checks, format checks):
Reproduction:
dotnet new console -n scl
cd scl
dotnet add package System.CommandLine
# Follow the tutorial through "Add subcommands and custom validation"
dotnet run -- quotes read --file nonexistent
# Expected: "File does not exist"
# Actual: Unhandled FileNotFoundException with stack trace
Page URL
https://learn.microsoft.com/en-us/dotnet/standard/commandline/get-started-tutorial#add-subcommands-and-custom-validation
Content source URL
https://github.com/dotnet/docs/blob/main/docs/standard/commandline/get-started-tutorial.md
Document Version Independent Id
fa160b1d-66ed-8c5d-37cd-b7e02443e9f1
Platform Id
0f144444-1ce3-cdf7-87a6-c659d44e08d3
Article author
@gewarren
Metadata
- ID: 7705dc41-7297-0807-7e9c-2e6548c26b84
- PlatformId: 0f144444-1ce3-cdf7-87a6-c659d44e08d3
- Service: dotnet-fundamentals
Related Issues
Associated WorkItem - 566723
Type of issue
Code doesn't work
Description
The "Add subcommands and custom validation" section places file-existence validation inside
DefaultValueFactory:The article states:
This doesn't work.
DefaultValueFactoryonly runs when no value is provided for the option. When a user passes--file nofile,System.CommandLine's built-in parser converts the argument directly toFileInfo(which doesn't validate existence), bypassingDefaultValueFactoryentirely. The action handler then throws aFileNotFoundExceptionwith a stack trace.Suggested fix (option A — built-in validator):
Suggested fix (option B — custom validator with custom error message):
In both cases, DefaultValueFactory should be simplified to only handle the default:
References:
AcceptExistingOnly()extension method validates that a FileInfo, DirectoryInfo, or FileSystemInfo path exists before the action handler runs:Validators.Add()for custom validation beyond file existence (e.g., range checks, format checks):option.Validators.Add(result => { ... result.AddError("message"); });Reproduction:
Page URL
https://learn.microsoft.com/en-us/dotnet/standard/commandline/get-started-tutorial#add-subcommands-and-custom-validation
Content source URL
https://github.com/dotnet/docs/blob/main/docs/standard/commandline/get-started-tutorial.md
Document Version Independent Id
fa160b1d-66ed-8c5d-37cd-b7e02443e9f1
Platform Id
0f144444-1ce3-cdf7-87a6-c659d44e08d3
Article author
@gewarren
Metadata
Related Issues
Associated WorkItem - 566723