Skip to content

GrpcClient benchmark app crashes with System.CommandLine 2.0.0: "Cannot parse --url as System.Uri" #2694

@ilonatommy

Description

@ilonatommy

What version of gRPC and what language are you using?

C#, Grpc.Net.Client from source (master branch of grpc/grpc-dotnet), System.CommandLine 2.0.0 (as pinned in Directory.Packages.props).

What operating system (Linux, Windows,...) and version?

Windows (reproduced on benchmark machines "Grpc Intel Win" and locally on Windows 11). The issue is platform-independent.

What runtime / compiler are you using (e.g. .NET Core SDK version dotnet --info)

.NET 9+ (the benchmark app targets net9.0). Also reproduced on .NET 11 preview 2.

What did you do?

Built and ran the GrpcClient benchmark app (perf/benchmarkapps/GrpcClient) with a --url argument, as crank does in the ASP.NET Core perf pipeline:

dotnet run --project perf/benchmarkapps/GrpcClient -- --url http://10.0.0.122:5000 --scenario unary --protocol h2

The app defines:

var urlOption = new Option<Uri>("--url", ["-u"]) { Description = "The server url to request", Required = true };

System.CommandLine 2.0.0 has no built-in converter for System.Uri (upstream: dotnet/command-line-api#2574, milestoned for 3.0.0), so parsing crashes immediately.

Minimal repro:

UriRepro.csproj:

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <OutputType>Exe</OutputType>
    <TargetFramework>net9.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>enable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <PackageReference Include="System.CommandLine" Version="2.0.0" />
  </ItemGroup>
</Project>

Program.cs:

using System.CommandLine;

var urlOption = new Option<Uri>("--url", ["-u"]) { Description = "The server url", Required = true };

var rootCommand = new RootCommand("Minimal repro");
rootCommand.Add(urlOption);
rootCommand.SetAction((parseResult) =>
{
    var url = parseResult.GetValue(urlOption);
    Console.WriteLine($"Parsed URL: {url}");
});

return await rootCommand.Parse(args).InvokeAsync();

Run: dotnet run -- --url http://10.0.0.122:5000

What did you expect to see?

The app starts, parses the URL, and runs the benchmark scenario normally.

What did you see instead?

Unhandled exception: System.InvalidOperationException: Cannot parse argument 'http://10.0.0.122:5000' for option '--url' as expected type 'System.Uri'.
   at System.CommandLine.Binding.ArgumentConverter.GetValueOrDefault[T](ArgumentConversionResult result)
   at System.CommandLine.Parsing.OptionResult.GetValueOrDefault[T]()
   at System.CommandLine.Parsing.SymbolResult.GetValue[T](Option`1 option)
   at System.CommandLine.ParseResult.GetValue[T](Option`1 option)
   at GrpcClient.Program.<>c__DisplayClass19_0.<<Main>b__0>d.MoveNext()
     in perf/benchmarkapps/GrpcClient/Program.cs:line 107

This breaks all 48 Grpc benchmark tasks in the ASP.NET Core perf pipeline (pipeline 1208).

Anything else we should know about your project / environment?

Suggested fix — add a CustomParser to the --url option in perf/benchmarkapps/GrpcClient/Program.cs (the workaround documented in the upstream issue comments):

var urlOption = new Option<Uri>("--url", ["-u"])
{
    Description = "The server url to request",
    Required = true,
    CustomParser = result =>
    {
        var token = result.Tokens.SingleOrDefault();
        if (token is null || !Uri.TryCreate(token.Value, UriKind.Absolute, out var uri))
        {
            result.AddError("The --url option requires a valid absolute URI.");
            return null;
        }
        return uri;
    }
};

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions