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

25
elmah.io logo 23

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");

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 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);

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");

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 trial
Free 21-day trial No credit card required

Related exceptions

Frequently asked questions

Why does File.WriteAllText not create the folder?

It creates the file only. Create the folders with Directory.CreateDirectory first.

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.

No. It does nothing when the folder already exists, so it is safe to call every time.

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:

AI chat
Find the most frequent DirectoryNotFoundException in my production log and show me the line that throws it.

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

  1. Create a post-build and/or installation routine that will move the \roslyn subdirectory to \bin\roslyn.
  2. 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.