Skip to content

[Resilience] _CheckGrpcNetClientFactoryVersion target crashes on bracket-pinned Grpc.Net.ClientFactory #7565

@Ghost93

Description

@Ghost93

Description

The _CheckGrpcNetClientFactoryVersion MSBuild target shipped by Microsoft.Extensions.Http.Resilience (buildTransitive/net8.0/Microsoft.Extensions.Http.Resilience.targets) feeds the Grpc.Net.ClientFactory version string directly into [MSBuild]::VersionLessThan(...) without validating that it is a parseable Version.

When a consumer pins the package using NuGet bracket notation - either via <PackageReference ... Version="[x.y.z]" /> directly, or via Central Package Management (<PackageVersion ... Version="[x.y.z]" />) - the function throws and the whole build fails before any compilation happens.

Reproduction Steps

Single-file repro (repro.csproj, no source code needed):

<Project Sdk="Microsoft.NET.Sdk">
    <PropertyGroup>
        <TargetFramework>net10.0</TargetFramework>
        <EnableDefaultCompileItems>false</EnableDefaultCompileItems>
    </PropertyGroup>
    <ItemGroup>
        <PackageReference Include="Microsoft.Extensions.Http.Resilience" Version="10.7.0" />
        <PackageReference Include="Grpc.Net.ClientFactory" Version="[2.80.0]" />
    </ItemGroup>
</Project>
dotnet build repro.csproj

Expected behavior

Build succeeds. NuGet has accepted [x.y.z] (exact-version pin) as a valid Version string on PackageReference / PackageVersion for years; tooling that consumes it should either parse it as a VersionRange and extract the underlying Version, or skip the check rather than crash the build. The pinned version (2.80.0) is also well above the 2.64.0 threshold the target was designed to warn about, so the check has nothing to flag.

Actual behavior

error MSB4184: The expression "[MSBuild]::VersionLessThan([2.80.0], 2.64.0)" cannot be evaluated.
               Version string was not in a correct format.
    [/path/to/repro.csproj]

Build FAILED.
    0 Warning(s)
    1 Error(s)

Regression?

I have not bisected this. The _CheckGrpcNetClientFactoryVersion target was added in Microsoft.Extensions.Http.Resilience somewhere in the 8.x line; the same crash reproduces on 10.6.0 and 10.7.0 (latest at time of writing). I have not tested whether earlier major versions (e.g. 8.x, 9.x) without the target are affected - the bug only exists where the target exists.

Known Workarounds

Set <SuppressCheckGrpcNetClientFactoryVersion>true</SuppressCheckGrpcNetClientFactoryVersion> in the consuming project. This is documented in the warning text emitted by the same target, but it should not be required for consumers who are already on a compatible Grpc version and merely happen to pin it with brackets.

Configuration

Component Value
Microsoft.Extensions.Http.Resilience 10.6.0 and 10.7.0 (both reproduce identically)
Grpc.Net.ClientFactory 2.80.0 (any bracket-pinned version reproduces)
.NET SDK 10.0.100
OS Linux (Ubuntu under WSL) - same MSBuild logic on Windows, so likely also affected

The crash happens regardless of whether bracket notation is used directly on PackageReference or centrally on PackageVersion (CPM). Both code paths in the target are vulnerable.

Other information

Affected file:
src/Libraries/Microsoft.Extensions.Http.Resilience/buildTransitive/net*/Microsoft.Extensions.Http.Resilience.targets

All four [MSBuild]::VersionLessThan(...) call sites in that file have the same problem:

  • %(_GrpcNetClientFactoryPackageReference.Version) (line ~30)
  • %(_GrpcNetClientFactoryPackageReference.VersionOverride) (line ~37)
  • %(_GrpcNetClientFactoryPackageVersion.Version) (line ~44)
  • %(_GrpcNetClientFactoryTransitiveDependency.NuGetPackageVersion) (line ~51)

Suggested fix: strip leading [ / trailing ] (and any version-range second element like [1.0.0,2.0.0)) before invoking VersionLessThan. Bracket notation is part of the public NuGet contract; the target should tolerate it.

Note that the official Known Issues docs describe this check as producing a "compilation warning" - but with bracket-pinned Version, it produces a build-failing MSB4184 error before any warning is emitted. The contract documented in the Known Issues section is therefore violated for any consumer that pins versions with [x.y.z] notation, even when they're already on a fully compatible Grpc version.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugThis issue describes a behavior which is not expected - a bug.untriaged

    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