Search code examples
.netf#azure-pipelinesdotnet-sdk

Azure Pipeline fails on `dotnet build` with error "command or file was not found"


Recently I had Azure Pipeline builds start failing, without any changes to my build scripts/yaml. The errors are as follows but they're still pretty light on the details.

C:\hostedtoolcache\windows\dotnet\sdk\3.1.406\FSharp\Microsoft.FSharp.Targets(279,9): error MSB6006: "dotnet.exe" exited with code 1. [D:\a\1\s\src\App.Core\App.Core.fsproj]

##[error]Error: The process 'C:\hostedtoolcache\windows\dotnet\dotnet.exe' failed with exit code 1

To get more information I also adding the --verbosity detailed to the build step which revealed the following details.

Could not execute because the specified command or file was not found.
Possible reasons for this include:
    * You misspelled a built-in dotnet command.
    * You intended to execute a .NET Core program, but dotnet-@C:\Users\VssAdministrator\AppData\Local\Temp\tmp3147e93b44f0436c9449d0f384ba6079.rsp does not exist.
    * You intended to run a global tool, but a dotnet-prefixed executable with this name could not be found on the PATH.

So the build seems to fail while attempting to use an msbuild response file. However, this seems like an internal issue and not an issue with my command. I don't know much about how dotnet build uses msbuild internally.

There's also a warning and an info line in the logs. However, they should not apply because I am using the dotnet cli to restore and I'm using UseDotNet to install SDK Version 3.1.409 with the same version in the global.json

##[warning].NET 5 has some compatibility issues with older Nuget versions(<=5.7), so if you are using an older Nuget version(and not dotnet cli) to restore, then the dotnet cli commands (e.g. dotnet build) which rely on such restored packages might fail. To mitigate such error, you can either: (1) - Use dotnet cli to restore, (2) - Use Nuget version 5.8 to restore, (3) - Use global.json using an older sdk version(<=3) to build
Info: Azure Pipelines hosted agents have been updated and now contain .Net 5.x SDK/Runtime along with the older .Net Core version which are currently lts. Unless you have locked down a SDK version for your project(s), 5.x SDK might be picked up which might have breaking behavior as compared to previous versions. You can learn more about the breaking changes here: https://learn.microsoft.com/en-us/dotnet/core/tools/ and https://learn.microsoft.com/en-us/dotnet/core/compatibility/ . To learn about more such changes and troubleshoot, refer here: https://learn.microsoft.com/en-us/azure/devops/pipelines/tasks/build/dotnet-core-cli?view=azure-devops#troubleshooting

Contents of the global.json file:

{
  "sdk": {
    "version": "3.1.409",
    "rollForward": "latestFeature"
  }
}

In the build pipeline packages are restored in a separate step before the build. There is also one project (dbup) that is built before the full build (dotnet build) which succeeds. While the full build step fails. I have included the relevant steps from the azure-pipelines.yml file.

    steps:
      - task: UseDotNet@2
        displayName: 'Use .Net Core sdk 3.1.409'
        inputs:
          version: 3.1.409

      - task: DotNetCoreCLI@2
        displayName: 'dotnet restore'
        inputs:
          command: restore
          projects: App.sln

      - task: DotNetCoreCLI@2
        displayName: 'dotnet build dbup'
        inputs:
          command: build
          projects: 'src\App.DatabaseUp\App.DatabaseUp.fsproj'
          arguments: '--no-restore --configuration release --version-suffix $(Build.BuildNumber)'

      - task: DotNetCoreCLI@2
        displayName: 'dotnet build'
        inputs:
          command: build
          projects: App.sln
          arguments: '--no-restore --configuration release --version-suffix $(Build.BuildNumber)'

So far I've tried using different SDK versions (3.1.406 and 3.1.409) and I've checked all the recommendations in the warnings and info messages. It's also worth noting that, the project does build successfully using dotnet build locally. All the projects in the solution target netcoreapp3.1

I assume the issue is due to an image update as I'm using vmImage: 'windows-latest' however I can't see any issue and I've run out of ideas.


Update

The file and line number from Microsoft.FSharp.Targets(279,9) seems to indicate that this is an issue calling the FSharp Compiler.

This also lines up with the issue in the vs developer community unable to build fsharp project using dotnet build. The thread contains the following relevant section, however it gives no indication as to why or how $(PathToFsc) could be empty.

Existing error message accurately conveys the issue; it’s not F#-specific. Something in the .props/.targets files evaluates to dotnet $(PathToFsc) some/file.rsp and the variable $(PathToFsc) (or whatever is in your build scripts) is evaluating to an empty string. The final command that’s executed is then dotnet some/file.rsp and the normal dotnet behavior is to look for dotnet-<argument> as an executable.


Solution

  • The issue was in fact due to the FscToolPath evaluating to an empty string.

    Existing error message accurately conveys the issue; it’s not F#-specific. Something in the .props/.targets files evaluates to dotnet $(PathToFsc) some/file.rsp and the variable $(PathToFsc) (or whatever is in your build scripts) is evaluating to an empty string. The final command that’s executed is then dotnet some/file.rsp and the normal dotnet behavior is to look for dotnet- as an executable.

    The second factor was that the location of FSC did change due to an update of Visual Studio on the VM Image.

    Not an answer, but I wonder if it's related to this: stackoverflow.com/questions/67800998/… - it seems things may have moved between VS 16.9 and 16.10.

    Finally why it impacted me was because I was setting the FscCompilerPath manually due to a TypeProvider that did not support the dotnet core pipeline due to a dependency on System.Data.SqlClient.

    <DisableAutoSetFscCompilerPath>true</DisableAutoSetFscCompilerPath>
    
    <PropertyGroup Condition="'$(IsWindows)' == 'true' AND Exists('C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\FSharp\fsc.exe')">
      <FscToolPath>C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\FSharp</FscToolPath>
      <FscToolExe>fsc.exe</FscToolExe>
    </PropertyGroup>
    

    So updating the FscToolPath to C:\Program Files (x86)\Microsoft Visual Studio\2019\Professional\Common7\IDE\CommonExtensions\Microsoft\FSharp\Tools resolved the issue.