System.IO.DirectoryNotFoundException
A DirectoryNotFoundException is thrown when part of a path does not exist. The message is Could not find a part of the path, followed by the full path. It is thrown when you read from or write to a file in a folder that is not there, and when you list the contents of a folder that does not exist.
Opening a missing file in an existing folder throws a FileNotFoundException instead.
Minimum version: >= 1.1 >= Core 1.0
Statistics
Common causes
A folder in the path is missing, or is not available to the process. These are the usual cases.
Writing a file to a folder that does not exist
File.WriteAllText creates the file, but not the folders above it. A new environment without the export folder fails on the first write.
File.WriteAllText(@"C:\exports\2026\export.csv", "id,name"); // DirectoryNotFoundException
Create the folder first. CreateDirectory does nothing when the folder already exists:
var path = @"C:\exports\2026\export.csv";
Directory.CreateDirectory(Path.GetDirectoryName(path));
File.WriteAllText(path, "id,name");
Listing a folder that does not exist
Directory.GetFiles and Directory.EnumerateFiles throw when the folder is missing, instead of returning an empty list.
var files = Directory.GetFiles(@"C:\exports\2026"); // DirectoryNotFoundException
Check that the folder exists, and treat a missing folder as empty:
var folder = @"C:\exports\2026";
var files = Directory.Exists(folder) ? Directory.GetFiles(folder) : Array.Empty<string>();
A mapped drive or share that the process cannot see
A drive letter that is mapped for your user is not mapped for a service, a scheduled task or an IIS application pool. The path works when you test it, and fails when the application runs under another account.
Use the UNC path, such as \\server\share\folder, and give the account that runs the application access to the share.
How to fix it and prevent it
Create folders before you write
Directory.CreateDirectory creates every missing folder in the path, and does nothing when it already exists. Call it before you write, or once when the application starts.
var folder = Path.Combine(AppContext.BaseDirectory, "exports");
Directory.CreateDirectory(folder);
Build paths with Path.Combine and known folders
Hard-coded drive letters and separators break when the application moves to another machine or operating system. Use Path.Combine and Environment.GetFolderPath.
var folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Shop", "exports");
Check configured paths when the application starts
If the folder comes from configuration, check it when the application starts and fail with a clear message. That is easier to fix than an exception in the middle of a request.
var exportFolder = configuration["ExportFolder"]
?? throw new InvalidOperationException("ExportFolder is not configured.");
Directory.CreateDirectory(exportFolder);
How to find the missing folder
The message contains the full path, so start there. The stack trace shows which call used it:
System.IO.DirectoryNotFoundException: Could not find a part of the path 'C:\exports\2026\export.csv'.
at Microsoft.Win32.SafeHandles.SafeFileHandle.CreateFile(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options)
at Microsoft.Win32.SafeHandles.SafeFileHandle.Open(String fullPath, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize, Nullable`1 unixCreateMode)
at System.IO.File.OpenHandle(String path, FileMode mode, FileAccess access, FileShare share, FileOptions options, Int64 preallocationSize)
at System.IO.File.WriteToFile(String path, FileMode mode, ReadOnlySpan`1 contents, Encoding encoding)
at System.IO.File.WriteAllText(String path, String contents, Encoding encoding)
at Shop.Services.ExportService.Save(String content) in C:\src\Shop\Services\ExportService.cs:line 14
at Program.<Main>$(String[] args) in C:\src\Shop\Program.cs:line 4
The path is C:\exports\2026\export.csv, and the call that used it is line 14 of ExportService.cs. The message does not say which part of the path is missing. Check each folder from the root, and look for a drive that is not available to the account that runs the application.
Should you catch it?
It can make sense to catch it around file operations, for example to show the user that a folder is not available. When the folder is one you own, create it instead.
Log the full path from the message, so you can see which folder is missing.
Find DirectoryNotFoundException before your users do
elmah.io logs every unhandled exception in your .NET application with its stack trace and request details, groups identical errors and notifies you when a new one appears.
Start free trialRelated exceptions
- FileNotFoundException is thrown when the folder exists, but the file does not.
- IOException is the base class, and is thrown for other file problems.
- UnauthorizedAccessException is thrown when the folder exists, but the process may not use it.
Frequently asked questions
Why does File.WriteAllText not create the folder?
It creates the file only. Create the folders with Directory.CreateDirectory first.
Why does my path work in Visual Studio but not on the server?
The server may not have the folder, the drive letter or the share. Services and IIS also run as other accounts than you, with their own mapped drives and permissions.
Does Directory.CreateDirectory throw if the folder exists?
No. It does nothing when the folder already exists, so it is safe to call every time.
What is the difference between DirectoryNotFoundException and FileNotFoundException?
A DirectoryNotFoundException means a folder in the path is missing. A FileNotFoundException means the folders exist, but the file does not.
Let your AI agent track it down
Connect Claude Code, Cursor, VS Code or Visual Studio to the elmah.io MCP server and ask your agent to look into DirectoryNotFoundException for you. For example:
The agent reads the stack trace and request details from elmah.io, finds the code in your repository and proposes a fix. In Claude Code, add the server with one command:
claude mcp add --transport http --client-id claudecode elmahio https://mcp.elmah.io/mcp
The MCP server is included on every plan and is currently in beta. Set up the MCP server.
Further reading
YouTube videos
Answers from Stack Overflow
Ended up finding the answer.
The following is needed to read the relative paths in a WebApi project:
var fullPath = System.Web.Hosting.HostingEnvironment.MapPath(@"~/App_Data/yourXmlFile.xml");
By user1352057. Read the original answer on Stack Overflow.
Update: March 2018
Word of caution, NuGet version 1.0.6 ... 1.0.8 will not copy the /roslyn folder to the build output directory on non-web projects. Best stick with 1.0.5 https://github.com/aspnet/RoslynCodeDomProvider/issues/38
Run-time compilation using C#6 features requires a new compiler, as @thomas-levesque mentioned. This compiler can be installed by using the nuget package Microsoft.CodeDom.Providers.DotNetCompilerPlatform.
For desktop applications, there's a problem. The ASP.NET team, in their infinite wisdom have hard-coded the path to the compiler as <runtime-directory>\bin\roslyn\csc.exe See discussion at https://github.com/dotnet/roslyn/issues/9483
If your desktop application is compiled to \myapp\app.exe, the roslyn compiler will be located at \myapp\roslyn\csc.exe, BUT THE CSharpCodeProvider WILL RESOLVE csc.exe as \myapp\bin\roslyn\csc.exe
As far as I can tell, you have two options
- Create a post-build and/or installation routine that will move the
\roslynsubdirectory to\bin\roslyn. - Fix the runtime code through reflection black magic.
Here is #2, by exposing the CSharpCodeProvider as a property in a utility class.
using System.Reflection;
using Microsoft.CodeDom.Providers.DotNetCompilerPlatform;
static Lazy<CSharpCodeProvider> CodeProvider { get; } = new Lazy<CSharpCodeProvider>(() => {
var csc = new CSharpCodeProvider();
var settings = csc
.GetType()
.GetField("_compilerSettings", BindingFlags.Instance | BindingFlags.NonPublic)
.GetValue(csc);
var path = settings
.GetType()
.GetField("_compilerFullPath", BindingFlags.Instance | BindingFlags.NonPublic);
path.SetValue(settings, ((string)path.GetValue(settings)).Replace(@"bin\roslyn\", @"roslyn\"));
return csc;
});
By Aaron Hudon. Read the original answer on Stack Overflow.
The built-in CodeDOM provider doesn't support C# 6. Use this one instead:
https://www.nuget.org/packages/Microsoft.CodeDom.Providers.DotNetCompilerPlatform/
It's based on Roslyn and supports the C# 6 features.
Just change this line:
CodeDomProvider objCodeCompiler = CodeDomProvider.CreateProvider( "CSharp" );
to this:
CodeDomProvider objCodeCompiler = new Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider();
By Thomas Levesque. Read the original answer on Stack Overflow.
The folder may created in your C:\( the default drive where OS is installed). that is folder location is C:\Logs\WZCLogs\. you can confirm that a folder is created somewhere in the drive-by executing the code again, this time the if (!Directory.Exists(FilePath)) returns true. Since you have not specified any location the compiler assumes So. Check whether it is created or not;
You can extend the try Like this:
try
{
Directory.CreateDirectory(FilePath);
}
catch (Exception ex)
{
// handle them here
}
If the path is a wrong one definitely an exception will be thrown; I have tried with "X:\sample" which gives me the exception:
Could not find a part of the path 'X:\sample
Whereas if I tried with Logs\WZCLogs which won't give any exception for the first time and also skip the if for the second time; Hence I found that the folder is created somewhere else;
You can make these changes to make them work:
string FilePath=Path.Combine(HostingEnvironment.ApplicationPhysicalPath, @"Logs\WZCLogs");
By sujith karivelil. Read the original answer on Stack Overflow.
The long and the short answer is that this isn't possible. Unlike Java, none of the .NET languages require that functions report a list of possible exceptions that can be thrown (which means that you either have to catch or report any exceptions that could be thrown on functions that it calls). Because of this, there's no generic way to determine an exhaustive list of every exception that a function could throw (I'm using the word function here to cover anything that's written like a function, including operators, constructors, etc.) because you have no guarantee as to the exceptions that could be thrown by what a given function might call.
If you're willing to go in limited, then it's conceivable that you could write something that could scan MSDN for the appropriate article for a given .NET library call and use the list of exceptions there (if any) to recursively establish a list of what could possibly be thrown. This wouldn't, however, cover any third-party libraries or catch any exceptions thrown by the runtime (OutOfMemoryException, StackOverflowException, NullReferenceException [unless you want to take it a step further and have your exception analysis also determine if there is any possibility of a null reference, but this, too, seems impossible to do in a completely generic sense]).
I'm pretty sure that this has been covered a time or two by the C# team (I'd be surprised if Eric Lippert hasn't already answered a question about this on SO), but I'm pretty certain that it boiled down to this: While this sort of system is useful and valuable to some people, mandating its use (and forcing you either to report or catch all possibly thrown exceptions) led to a lot of try { ... } catch (Exception ex) { ... } blocks in order to avoid the housekeeping, and blanket, silent catches are a lot worse (IMHO) than an unreported exception.
By Adam Robinson. Read the original answer on Stack Overflow.
Source: Stack Overflow