Could not find assembly deploying a dotnet 6 console app

Problem

After deploying a dotnet 6 console app to a production server, I got the following error:

Exception: [Could not load file or assembly 'System.Data.Odbc, Version=6.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'. The system cannot find the file specified.]

The strange thing was the same EXE, built on a Microsoft hosted Azure DevOps build agent, was working on the test server and was deployed using the same Azure DevOps Pipeline to both systems.

I tried many things to work out what the problem was. My first though was Fuslogvw, but found out I should be using dotnet-trace, but this showed nothing other than the assembly was not found i.e. no downstream dependencies were missing.

I then manually pulled the same deployment ZIP onto the server, unpacked it and ran the EXE from the command line, it worked - what was the difference?

Solution

Eventually I spotted the problem, the runtimes folder was missing on the copy that was deployed via the pipeline.

My automated deployment look like this

Bad folder structure

But my manual deploy had a runtimes folder with the platform specific folders in the runtimes folder

Good folder structure

Remember, the same deployment pipeline was deploying the same artifact to both the test and production servers, and I could see the folder structure was correct in the build agent staging folder (where the ZIp was expanded prior to the copy). So why the differences?

And it got stranger, I redeployed the package using the same pipelines (just a re-run stage, not a complete now run) and this time the runtimes folder was there, and the EXE worked!

Conclusion

I am just going to put this one down to a glitch in the matrix, maybe related to debris in the target folder?

But the learning is, when you get missing assembly errors with a .NET 6 (or .NET Core) deployment make sure the runtime folder is present and contains the platform specific folders.

Also make sure your target folder is empty before copying in the new code to avoid any debris from previous deployments just to be on the safe side.