`dotnet tool install` on non-tool package causes DirectoryNotFoundException
Describe the bug
When I use dotnet tool install on a package that is not a .NET tool package, it fails with an unhandled DirectoryNotFoundException. It should instead report that the package type is wrong.
I initially hit this when I noticed https://github.com/dotnet/sourcelink/pull/678 and attempted to install dotnet-sourcelink, which turned out to be an older package that has <packageType name="DotnetCliTool" /> rather than <packageType name="DotnetTool" />, and does not contain a tools directory.
To Reproduce
dotnet tool install --global System.ValueTuple --version 4.5.0
Exceptions (if any)
Unhandled exception: System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\Users\Kalle\.dotnet\tools\.store\system.valuetuple\4.5.0\system.valuetuple\4.5.0\tools'.
at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
at System.IO.Enumeration.FileSystemEnumerator`1.Init()
at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
at System.IO.Enumeration.FileSystemEnumerableFactory.UserDirectories(String directory, String expression, EnumerationOptions options)
at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
at System.IO.Directory.GetDirectories(String path, String searchPattern, EnumerationOptions enumerationOptions)
at Microsoft.DotNet.ToolPackage.ToolPackageInstance..ctor(PackageId id, NuGetVersion version, DirectoryPath packageDirectory, DirectoryPath assetsJsonParentDirectory)
at Microsoft.DotNet.Cli.ToolPackage.ToolPackageDownloader.<>c__DisplayClass8_0.<InstallPackage>b__0()
at Microsoft.DotNet.Cli.TransactionalAction.Run[T](Func`1 action, Action commit, Action rollback)
at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.Execute()
at System.CommandLine.Invocation.InvocationPipeline.Invoke(ParseResult parseResult)
at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)
Further technical details
$ dotnet --info
.NET SDK:
Version: 8.0.100
Commit: 57efcf1350
Workload version: 8.0.100-manifests.71b9f198
Runtime Environment:
OS Name: Windows
OS Version: 10.0.19045
OS Platform: Windows
RID: win-x64
Base Path: C:\Program Files\dotnet\sdk\8.0.100\
.NET workloads installed:
Workload version: 8.0.100-manifests.71b9f198
[aspire]
Installation Source: SDK 8.0.100
Manifest Version: 8.0.0-preview.1.23557.2/8.0.100
Manifest Path: C:\Program Files\dotnet\sdk-manifests\8.0.100\microsoft.net.sdk.aspire\8.0.0-preview.1.23557.2\WorkloadManifest.json
Install Type: Msi
Host:
Version: 8.0.0
Architecture: x64
Commit: 5535e31a71
.NET SDKs installed:
2.1.526 [C:\Program Files\dotnet\sdk]
6.0.417 [C:\Program Files\dotnet\sdk]
8.0.100 [C:\Program Files\dotnet\sdk]
.NET runtimes installed:
Microsoft.AspNetCore.All 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.All]
Microsoft.AspNetCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.AspNetCore.App]
Microsoft.NETCore.App 2.1.30 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.2 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.NETCore.App]
Microsoft.WindowsDesktop.App 6.0.2 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 6.0.25 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Microsoft.WindowsDesktop.App 8.0.0 [C:\Program Files\dotnet\shared\Microsoft.WindowsDesktop.App]
Other architectures found:
x86 [C:\Program Files (x86)\dotnet]
registered at [HKLM\SOFTWARE\dotnet\Setup\InstalledVersions\x86\InstallLocation]
Environment variables:
Not set
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
No IDE.
Thanks for reporting that
Quick note here that it doesn't look like the ToolPackageDownloader is validating that the given package id is a tool or not, so we should do that and fail with a validation error instead of allowing non-tool packages to be downloaded.
I have the same issue. I am on Linux, Ubuntu 22.04, 6.4.6-060406-generic. I am running this command
dotnet tool install --global MathNet.Numerics --version 5.0.0
and I am getting this error:
~/.dotnet$ dotnet tool install --global MathNet.Numerics --version 5.0.0
Skipping NuGet package signature verification.
Unhandled exception: System.IO.DirectoryNotFoundException: Could not find a part of the path '/home/ihor/.dotnet/tools/.store/mathnet.numerics/5.0.0/mathnet.numerics/5.0.0/tools'.
at System.IO.Enumeration.FileSystemEnumerator`1.CreateDirectoryHandle(String path, Boolean ignoreNotFound)
at System.IO.Enumeration.FileSystemEnumerator`1.Init()
at System.IO.Enumeration.FileSystemEnumerable`1..ctor(String directory, FindTransform transform, EnumerationOptions options, Boolean isNormalized)
at System.IO.Enumeration.FileSystemEnumerableFactory.UserDirectories(String directory, String expression, EnumerationOptions options)
at System.IO.Directory.InternalEnumeratePaths(String path, String searchPattern, SearchTarget searchTarget, EnumerationOptions options)
at System.IO.Directory.GetDirectories(String path, String searchPattern, EnumerationOptions enumerationOptions)
at Microsoft.DotNet.ToolPackage.ToolPackageInstance..ctor(PackageId id, NuGetVersion version, DirectoryPath packageDirectory, DirectoryPath assetsJsonParentDirectory)
at Microsoft.DotNet.Cli.ToolPackage.ToolPackageDownloader.<>c__DisplayClass8_0.<InstallPackage>b__0()
at Microsoft.DotNet.Cli.TransactionalAction.Run[T](Func`1 action, Action commit, Action rollback)
at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.<>c__DisplayClass18_0.<Execute>b__1()
at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.RunWithHandlingInstallError(Action installAction)
at Microsoft.DotNet.Tools.Tool.Install.ToolInstallGlobalOrToolPathCommand.Execute()
at System.CommandLine.Invocation.InvocationPipeline.Invoke(ParseResult parseResult)
at Microsoft.DotNet.Cli.Program.ProcessArgs(String[] args, TimeSpan startupTime, ITelemetry telemetryClient)
My dotnet --info:
.NET SDK:
Version: 8.0.201
Commit: 4c2d78f037
Workload version: 8.0.200-manifests.3097af8b
Runtime Environment:
OS Name: ubuntu
OS Version: 22.04
OS Platform: Linux
RID: linux-x64
Base Path: /home/ihor/.dotnet/sdk/8.0.201/
.NET workloads installed:
There are no installed workloads to display.
Host:
Version: 8.0.2
Architecture: x64
Commit: 1381d5ebd2
.NET SDKs installed:
5.0.408 [/home/ihor/.dotnet/sdk]
8.0.201 [/home/ihor/.dotnet/sdk]
.NET runtimes installed:
Microsoft.AspNetCore.App 5.0.17 [/home/ihor/.dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.AspNetCore.App 8.0.2 [/home/ihor/.dotnet/shared/Microsoft.AspNetCore.App]
Microsoft.NETCore.App 5.0.17 [/home/ihor/.dotnet/shared/Microsoft.NETCore.App]
Microsoft.NETCore.App 8.0.2 [/home/ihor/.dotnet/shared/Microsoft.NETCore.App]
Other architectures found:
None
Environment variables:
DOTNET_ROOT [/home/ihor/.dotnet]
global.json file:
Not found
Learn more:
https://aka.ms/dotnet/info
Download .NET:
https://aka.ms/dotnet/download
@ibobak, if this bug is fixed, then dotnet tool install MathNet.Numerics --version 5.0.0 will still fail; it will just detect the problem earlier and display the error in a prettier way.