Updated on
The “Could not execute because the specified command or file was not found” error means the .NET SDK can’t find the dotnet ef tool. We fix it by installing the tool, either for our user account or as a local tool that lives with our project.
The SDK stopped shipping dotnet ef with EF Core 3.0, so a fresh SDK install starts without it.
Let’s start.
Why Does dotnet ef Say the Command or File Was Not Found?
dotnet ef isn’t a built-in command of the .NET SDK. It’s a separate tool, and when we type dotnet ef, the SDK goes looking for a tool called dotnet-ef.
It searches two install locations. First, a local tool manifest in the current folder or any folder above it. Then the PATH, which is where global tools live.
When neither search finds the tool, the SDK gives up with “Could not execute because the specified command or file was not found” and lists three possible reasons.
On a new machine or a fresh build agent, the cause is almost always the simple one: nobody installed the tool. The SDK doesn’t ship it, so every new environment starts without it.
Less often, the tool is installed but the shell can’t see it. A global tool whose folder isn’t on the PATH, or a local tool whose manifest sits in a folder below or beside the one we’re working in, produces exactly the same message.
Before we start, we want to mention that we are not going to talk about how to create migrations in EF Core. We assume you are already familiar with that. Of course, to learn more about EF Core Migrations, you can check out our article on how migrations work in EF Core.
Now, let’s continue.
Let’s imagine we’re following the code-first approach with a Customer.cs class, and we intend to create a database with a Customer table:
public class Customer
{
public Guid Id { get; set; }
public string? FirstName { get; set; }
public string? LastName { get; set; }
public int Age { get; set; }
public string? Address { get; set; }
public string? CardNumber { get; set; }
}
Then, if we try to run EF Core migrations using dotnet ef migrations add InitialCreate, we are going to get an error:
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 program, but dotnet-ef 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.
We got this exact text from .NET SDK 10.0.302.
From this error, we understand that we have an issue related to our command and we also see several reasons that can cause it:
The first one, You misspelled a built-in dotnet command, is basically not true because we use the command from Microsoft’s official documentation.
Let’s check the second one, You intended to execute a .NET program, but dotnet-ef does not exist. This can lead us to our solution for the issue since we are obviously missing something.
Let’s continue inspecting the last one, which mentions the global tool and a not found path. It should help us as well since we use a dotnet ef command and it is not recognized on our machine, so it is somehow similar to the second reason.
So, for sure, we are missing something. But what is it, and how to fix it?
How Do We Install the dotnet ef Tool Globally?
If we inspect this announcement for Entity Framework Core 3.0 Preview 4, we can find that the dotnet ef tool is no longer part of the .NET Core SDK. That’s why in our example, we can’t execute the migration.
Microsoft Learn’s EF Core tools reference says dotnet ef “can be installed as either a global or local tool.” We’ll start with the global one, which is what most of us reach for first.
That said, we should install the dotnet ef tool on our machine:
dotnet tool install --global dotnet-ef
A global tool goes into %USERPROFILE%\.dotnet\tools on Windows and $HOME/.dotnet/tools on Linux and macOS. The SDK tries to add that folder to our PATH the first time it runs, but Microsoft’s troubleshooting guide lists setups where that step doesn’t happen, among them recent macOS versions and Linux SDKs unpacked from a .tar.gz file.
So what if the install succeeds and dotnet ef still prints the same error? Then that folder isn’t on the PATH of the shell we’re using. A terminal that was already open when the PATH changed keeps its old copy, so opening a new one is the first thing to try. On Linux or macOS, if the folder is still missing, we add it to our shell profile (~/.bashrc for Bash, ~/.zshrc for Zsh):
export PATH="$PATH:$HOME/.dotnet/tools"
If the tool is already installed but older than our EF Core packages, we update it instead:
dotnet tool update --global dotnet-ef
Now we should be able to run our dotnet ef commands successfully.
Let’s execute our migration command again:
dotnet ef migrations add InitialCreate
And now we get a successful result:
Build started... Build succeeded. Done. To undo this action, use 'ef migrations remove'
That last line points at ef migrations remove, and our guide to reverting an EF Core migration covers it, along with rolling back a migration we’ve already applied.
Then, to apply our changes to the database, we have to execute a new command:
dotnet ef database update
And if we inspect the message:
Build started... Build succeeded. Acquiring an exclusive lock for migration application. See https://aka.ms/efcore-docs-migrations-lock for more information if this takes too long. Applying migration '20220401210459_InitialCreate'. Done.
We can see that we’ve applied our migration successfully.
That’s fine for a local database. For a production one, our article on applying migrations in production covers SQL scripts and migration bundles instead.
How Do We Install dotnet ef as a Local Tool?
A local tool belongs to a folder instead of our user account. Its name and version live in a dotnet-tools.json manifest that we commit with our code, so everyone who clones the repository runs the same dotnet ef version.
We set it up with two commands in the solution folder. dotnet new tool-manifest creates the manifest, and dotnet tool install dotnet-ef, without --global, adds the tool to it.
From then on, dotnet ef works in that folder and every folder below it, because the SDK walks up from the current folder until it finds a manifest.
A teammate or a CI job that clones the repository runs one command, dotnet tool restore, and gets exactly the version the manifest names.
This is the route we’d pick for a team project. The global install is quicker on our own machine, but it’s one version for every project, and nothing in the repository tells the next developer they need it.
Let’s add it to our project. In the solution folder, we create the manifest and install the tool into it:
dotnet new tool-manifest dotnet tool install dotnet-ef
The install tells us how to call the tool from this folder:
You can invoke the tool from this directory using the following commands: 'dotnet tool run dotnet-ef' or 'dotnet dotnet-ef'. Tool 'dotnet-ef' (version '10.0.13') was successfully installed. Entry is added to the manifest file ...\DotnetEfNotFoundError\dotnet-tools.json.
Plain dotnet ef works as well, and that’s what we keep using. The manifest now records the tool and its version:
{
"version": 1,
"isRoot": true,
"tools": {
"dotnet-ef": {
"version": "10.0.13",
"commands": [
"dotnet-ef"
],
"rollForward": false
}
}
}
Anyone who clones the repository installs the same version with one command:
dotnet tool restore
And gets:
Tool 'dotnet-ef' (version '10.0.13') was restored. Available commands: dotnet-ef Restore was successful.
We keep the tool on the same version as the EF Core packages in the project, 10.0.13 for both in our sample. Our sample repository carries this manifest, so dotnet tool restore is all it takes to get the tool there.
What If dotnet ef Runs but the Migration Still Fails?
Once the SDK finds the tool, the next error on a new project is often this one:
Your startup project 'CodeFirstMigration' doesn't reference Microsoft.EntityFrameworkCore.Design. This package is required for the Entity Framework Core Tools to work. Ensure your startup project is correct, install the package, and try again.
This time the tool runs, but our project is missing a package it needs. dotnet ef builds and runs our startup project to read the model and the connection string, and it needs Microsoft.EntityFrameworkCore.Design in that project to do it. We add it with:
dotnet add package Microsoft.EntityFrameworkCore.Design
Our sample’s project file already references it, which is why the migration in the previous sections worked.
Conclusion
We have explained the reasons behind the “dotnet ef not found” error and learned how to fix it with our example: a global install for our own machine, or a local tool manifest that travels with the repository.
For what comes after the first migration, our EF Core series covers relationships, queries and the rest of the day-to-day work.
Tested with .NET SDK 10.0.302, EF Core 10.0.13 and dotnet-ef 10.0.13.

Hello. Thought I’d share this since it may help others. I was able to get it to work by uninstalling and re-installing ef. thx
Thanks a lot, Kevin for this. Who knows, it might help somebody.
Thanks for the post! I thought my solution was also just needing to install the entity framework but when I try installing it, get the message that it was already installed (which I expected). ‘Tool ‘dotnet-ef’ is already installed.‘ Still getting ‘command or file not found’. Not sure why, but thanks anyway for the info.