- Published on
Fixing 'dotnet not found' on Linux (Bash, Zsh, Fish & CI)
- Authors

- Name
- Mathias Hove
- @mathias_hove
The problem
Have you ever experienced installing .NET on Linux just to find out that the following day executing dotnet in the terminal returns
dotnet: command not found
Or worse — it works in one terminal but not another. Or Rider works, VS Code works, but your shell doesn't. Or CI builds fail with:
The command "dotnet" could not be found
This post explains why that happens and how to fix it properly — across Bash, Zsh, Fish, and CI environments. Think of it as a debugging guide to help you understand why things stopped working and how to get them back on track.
Step 1: Confirm the actual problem
Before changing anything, verify that the system actually sees .NET.
Is dotnet on PATH?
which dotnet
If nothing prints → it's not on your PATH.
If you see something like:
/home/youruser/.dotnet/dotnet
Then it exists on the system, but your shell config might not be loading the .NET path correctly.
Verify installed SDKs
dotnet --info
This shows:
- SDK location
- Installed runtimes
- Base path
Typical install paths:
| Install method | Location |
|---|---|
| Microsoft apt repo | /usr/share/dotnet |
dotnet-install.sh | $HOME/.dotnet |
| Snap | /snap/bin/ |
Note: If you installed via
snap install dotnet-sdk, the binary lands in/snap/bin/, which is sometimes not on PATH in all shell contexts. The fixes below apply the same way — just use the correct path.
If dotnet --info works in one shell but not another → this is almost always a shell startup issue.
Understanding Linux shell startup files
Different files are loaded depending on:
- Login shell vs non-login shell
- Interactive vs non-interactive shell
- Which shell you use
Bash
Bash uses different startup files depending on how it's launched.
Login shell loads (in order, stops at the first one found)
~/.bash_profile~/.bash_login~/.profile
Bash checks these in order and only reads the first one it finds. This means if you have a ~/.bash_profile that doesn't source ~/.bashrc, your .bashrc exports won't load in login shells either.
Non-login interactive shell loads
~/.bashrc
Most terminals open non-login shells, so .bashrc is usually what matters.
Zsh
Zsh loads:
~/.zprofile(login shells)~/.zshrc(interactive shells)
If you added PATH changes to .profile, Zsh will not read them.
Fish
Fish ignores .bashrc, .profile, .zshrc entirely.
Fish uses:
~/.config/fish/config.fish
The real cause
If you installed .NET using the script:
./dotnet-install.sh
It installs to:
$HOME/.dotnet
But it does not permanently modify your PATH.
You must add these lines to the correct startup file:
export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$HOME/.dotnet
Why both?
PATHis what lets your shell find thedotnetcommand.DOTNET_ROOTis used separately by tools like Rider, VS Code, and OmniSharp to locate the SDK — they don't always rely on PATH alone.
The correct fix (by shell)
Bash
Edit:
nano ~/.bashrc
Add:
export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$HOME/.dotnet
Reload:
source ~/.bashrc
Zsh
Edit:
nano ~/.zshrc
Add:
export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$HOME/.dotnet
Reload:
source ~/.zshrc
Fish
Edit:
nano ~/.config/fish/config.fish
Add:
set -x DOTNET_ROOT $HOME/.dotnet
fish_add_path $HOME/.dotnet
Note:
fish_add_path(Fish 3.2+) is the idiomatic way to add to PATH in Fish — it handles deduplication and persistence automatically. If you're on an older version of Fish, useset -x PATH $PATH $HOME/.dotnetinstead.
Restart the terminal.
Login vs non-login shell gotcha
Run:
echo $0
If you see:
-bash
That's a login shell.
If you see:
bash
That's non-login.
If your PATH config is in .profile but your terminal runs non-login shells, it won't apply.
CI environments (GitHub Actions, Azure DevOps, etc.)
In CI, shell startup files usually do not run.
Install .NET explicitly in the pipeline.
GitHub Actions example
- name: Setup .NET
uses: actions/setup-dotnet@v4
with:
dotnet-version: "8.0.x"
Tip: Avoid relying on
.bashrc/.profilein CI. Treat pipelines as fresh machines.
Multiple SDKs + wrong version used
Sometimes dotnet exists, but the wrong SDK is selected.
Check installed SDKs:
dotnet --list-sdks
Pin the version with a global.json:
{
"sdk": {
"version": "8.0.401"
}
}
Quick diagnostic checklist
which dotnetdotnet --infoecho $PATHecho $0- Confirm correct shell config file
- Reload shell
- Open a new terminal
Linux is predictable once you understand shell startup order and how shells differ. Most "dotnet not found" errors are just misplaced environment variables.