System.IO.FileNotFoundException: Could not find file '/app/data\patients.json'. in a Linux container means the code built the path with a backslash. On Linux the backslash is part of the file name, not a separator. Build the path with Path.Combine or a forward slash.

In the test, File.ReadAllText(Path.Combine("data", "patients.json")) read the same file that "data\\patients.json" could not find.

The error

PS> docker run --rm --name fix10-dn-f1 fix10-dn-lab file
Unhandled exception. System.IO.FileNotFoundException: Could not find file '/app/data\patients.json'.
File name: '/app/data\patients.json'
...
   at System.IO.File.ReadAllText(String path, Encoding encoding)
   at Program.<Main>$(String[] args) in /src/Program.cs:line 10

Why it happens

Line 10 was File.ReadAllText("data\\patients.json"), the Windows way of writing it. In the container the working folder is /app, so the relative path became /app/data\patients.json: one file name with a backslash in it, inside /app. The file is there, under its folder:

PS> docker run --rm --name fix10-dn-f4 --entrypoint ls fix10-dn-lab -l /app/data
total 4
-rwxr-xr-x 1 root root 94 Nov 13 05:30 patients.json

The message itself shows the mix: forward slashes from the working folder, then one backslash from the code. That mix is the sign to look for. Read the path in the message before anything else: it is the full path the runtime tried, so it also shows which folder a relative path was resolved against. Here that was /app, the WORKDIR of the final stage.

The second line of the message, File name: '/app/data\patients.json', shows the backslash as well. Both failing runs in this post exited with code 139 and named the ReadAllText line of Program.cs (line 10 and line 14); the fixed call on the same image printed the file's contents.

The fix

Console.WriteLine(File.ReadAllText(Path.Combine("data", "patients.json")));
PS> docker run --rm --name fix10-dn-f3 fix10-dn-lab filefix
[{"name":"Maria Garcia","phone":"+00-555-0101"},{"name":"David Chen","phone":"+00-555-0102"}]

Path.Combine joins the two parts without a hard-coded separator in the code, and in the container it read the file that the backslash version could not find.

The second cause: letter case

The same exception came from a forward-slash path whose file name differed only in case: the code asked for Patients.json, the file is patients.json.

PS> docker run --rm --name fix10-dn-f2 fix10-dn-lab filecase
Unhandled exception. System.IO.FileNotFoundException: Could not find file '/app/data/Patients.json'.
File name: '/app/data/Patients.json'
...

The fix is the exact name as ls prints it, so compare the names in the code with the files in the image, not with the files in your project folder.

How it was reproduced

A console app built on mcr.microsoft.com/dotnet/sdk:10.0 (SDK 10.0.302) with data/patients.json published next to the DLL (CopyToPublishDirectory="PreserveNewest"), run on mcr.microsoft.com/dotnet/runtime:10.0 (Microsoft.NETCore.App 10.0.13) with WORKDIR /app. Docker engine 29.9.3 on Windows 11. The names in the data file are fictional.

Frequently asked

Why does my .NET app find the file on Windows but not in Docker?
In the test the code used data\patients.json. In the Linux container that became one file name with a backslash in it, /app/data\patients.json, which does not exist.
How do I build file paths that work on Windows and Linux in C#?
Use Path.Combine("data", "patients.json"). It read the file in the Linux container where the backslash path failed.
Are file names case sensitive in a .NET Linux container?
In the test, asking for Patients.json when the file was patients.json threw FileNotFoundException. Use the exact name shown by ls in the container.

More decoded errors in the Fixes category.