Fix dotnet tool exec / dnx failing when tool exists in dotnet-tools.json but not yet restored#53361
Conversation
…t not restored Co-authored-by: marcpopMSFT <12663534+marcpopMSFT@users.noreply.github.com>
dotnet tool exec failure with dotnet-tools.jsondotnet tool exec / dnx failing when tool exists in dotnet-tools.json but not yet restored
|
Confirmed that it didn't work before and now works with this fix. |
There was a problem hiding this comment.
Pull request overview
Fixes a regression in the CLI’s “one-shot” tool execution flow (dotnet tool exec / dnx) where the presence of a local tool manifest (.config/dotnet-tools.json) could cause execution to fail if the tool hadn’t been restored yet. The change ensures the manifest-based restore path persists restore results to the local tools resolver cache before resolving/running the tool.
Changes:
- Persist
ToolPackageRestorer.InstallPackage()’sSaveToCacheresult intoLocalToolsResolverCacheinToolExecuteCommand.Execute(). - Add an end-to-end regression test covering both
dotnet tool execanddnxwhen the tool is listed in a local manifest but not yet restored.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| src/Cli/dotnet/Commands/Tool/Execute/ToolExecuteCommand.cs | Saves newly restored local-tool command info into the resolver cache so resolution succeeds immediately after download. |
| test/Microsoft.DotNet.PackageInstall.Tests/EndToEndToolTests.cs | Adds regression coverage for the manifest-present-but-not-restored scenario for both exec and dnx. |
|
/backport to release/10.0.2xx |
|
/backport to release/10.0.1xx |
|
Started backporting to |
|
Started backporting to |
dotnet tool execanddnxfail with "Run 'dotnet tool restore' to make the command available" if the tool appears in a localdotnet-tools.jsonmanifest — even though these commands are supposed to handle downloading and running a tool without any prior setup.Root cause
In
ToolExecuteCommand.Execute(), the manifest-based path correctly callsToolPackageRestorer.InstallPackage(), which downloads the package and returns aSaveToCachetuple. However,localToolsResolverCache.Save()was never called with that result. The subsequentLocalToolsCommandResolverthen fails to find the tool in the (empty) cache and throws the error.Fix
ToolExecuteCommand.Execute()— save the restore result to the cache before invoking the resolver:Note:
SaveToCacheisnullwhenPackageHasBeenRestoredreturnstrue(tool already in the on-disk cache), so this only applies on first download — exactly the broken scenario.EndToEndToolTests— added regression testToolExecSucceedsWhenToolIsInLocalManifestButNotRestoredcovering bothexecanddnx, which creates adotnet-tools.jsonreferencing the tool and runs the command without a priordotnet tool restore.Original prompt
dotnet tool execanddnxdon't work ifdotnet-tools.jsonhappens to reference the same tool #53357✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.