System.UnauthorizedAccessException
An UnauthorizedAccessException is thrown when the operating system refuses an operation. The message is Access to the path 'C:\Temp' is denied. It is most often seen with files and folders, but it is also thrown for the registry and other protected resources.
The cause is not always a missing permission. Using a folder as if it were a file, and writing to a read-only file, give the same exception.
Minimum version: >= 1.1 >= Core 1.0
Statistics
Common causes
The path exists, but the operation was refused. These are the usual causes.
A folder that is used as a file
Opening a path that is a folder with a method that expects a file throws this exception, not a not-found exception. A missing file name in a configured path is a common reason.
var folder = Path.GetTempPath().TrimEnd(Path.DirectorySeparatorChar);
var text = File.ReadAllText(folder); // UnauthorizedAccessException: Access to the path is denied.
Use the folder methods for folders, and check what the path is:
var folder = Path.GetTempPath().TrimEnd(Path.DirectorySeparatorChar);
if (Directory.Exists(folder))
{
var files = Directory.GetFiles(folder);
}
A read-only file
A file with the read-only attribute cannot be written to or deleted, even by its owner.
var path = Path.GetTempFileName();
File.SetAttributes(path, FileAttributes.ReadOnly);
File.WriteAllText(path, "x"); // UnauthorizedAccessException
Clear the attribute first, if the file is yours to change:
var path = Path.GetTempFileName();
File.SetAttributes(path, FileAttributes.ReadOnly);
File.SetAttributes(path, FileAttributes.Normal);
File.WriteAllText(path, "x");
The account does not have permission
The process runs as a user, and that user may not have write access to the folder. An IIS application pool, a service and a container often run with less access than your own account, and folders such as Program Files and the website folder are read-only for them.
Write to a location that the account owns, such as a folder under LocalApplicationData or a temp folder. If the application needs another folder, give the account modify permission on that folder only.
How to fix it and prevent it
Write to a folder the application owns
Use Environment.GetFolderPath to find a folder that is meant for application data, and create a subfolder for your application. Do not write next to the executable.
var folder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Shop");
Directory.CreateDirectory(folder);
File.WriteAllText(Path.Combine(folder, "state.json"), "{}");
Give the account the least permission it needs
Grant modify access to the one folder the application writes to, for the account that runs it. Do not fix the problem by running the application as an administrator.
Check what the path points to
A path can be a file, a folder or missing. Check which it is before you pick the method, and report a missing file name in the configuration.
var path = configuration["ExportPath"] ?? "";
if (Directory.Exists(path))
{
path = Path.Combine(path, "export.csv");
}
How to find the cause
The message names the path, and the stack trace shows which call used it:
System.UnauthorizedAccessException: Access to the path 'C:\Temp' is denied.
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.SaveTo(String path, String content) in C:\src\Shop\Services\ExportService.cs:line 21
at Program.<Main>$(String[] args) in C:\src\Shop\Program.cs:line 4
Here the path is a folder, C:\Temp, and the call on line 21 of ExportService.cs wrote to it as if it were a file. If the path is a file, check its attributes and the permissions of the account that runs the application. Windows tools such as icacls show the permissions, and the user name can be logged at startup.
Should you catch it?
It can make sense to catch it around file operations on user-provided paths, and show a message that says which path was refused.
Do not catch it to ignore a permission problem on your own folders. That hides a setup problem that has to be fixed in the deployment.
Find UnauthorizedAccessException 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
- IOException is thrown when an operation fails for other reasons, such as a file in use.
- FileNotFoundException is thrown when the file does not exist.
- DirectoryNotFoundException is thrown when a folder in the path does not exist.
Frequently asked questions
Why do I get UnauthorizedAccessException when the file exists and I am an administrator?
The application may not run as you. Check the account of the process. The path may also be a folder, or the file may be read-only or locked with a specific access mode.
Why does it work on my machine but not in IIS?
The application pool identity has fewer permissions than your user. Grant it modify access to the folder it writes to, or write to a folder it owns.
Can I fix it by running the application as an administrator?
It may remove the exception, but it is not a good fix. It gives the application, and any bug or attack in it, more access than needed. Change the folder or its permissions instead.
Does the exception only apply to files?
No. It is also thrown for the registry, for some network and process operations, and for reflection on protected members.
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 UnauthorizedAccessException 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
UPDATE:
Modified the code based on this answer to get rid of obsolete methods.
You can use the Security namespace to check this:
public void ExportToFile(string filename)
{
var permissionSet = new PermissionSet(PermissionState.None);
var writePermission = new FileIOPermission(FileIOPermissionAccess.Write, filename);
permissionSet.AddPermission(writePermission);
if (permissionSet.IsSubsetOf(AppDomain.CurrentDomain.PermissionSet))
{
using (FileStream fstream = new FileStream(filename, FileMode.Create))
using (TextWriter writer = new StreamWriter(fstream))
{
// try catch block for write permissions
writer.WriteLine("sometext");
}
}
else
{
//perform some recovery action here
}
}
As far as getting those permission, you are going to have to ask the user to do that for you somehow. If you could programatically do this, then we would all be in trouble ;)
It seems that the problem is that kind of a File.Exists() check is done internally, which fails if the file is hidden (e.g. tries to do a FileMode.Create on a file which already exists).
Therefore, use FileMode.OpenOrCreate to make sure that the file is opened or created even if it is hidden, or just FileMode.Open if you do not want to create it if it doesn't exist.
When FileMode.OpenOrCreate is used though, the file will not be truncated, so you should set its length at the end to make sure that there is no leftover after the end of the text.
using (FileStream fs = new FileStream(filename, FileMode.Open)) {
using (TextWriter tw = new StreamWriter(fs)) {
// Write your data here...
tw.WriteLine("foo");
// Flush the writer in order to get a correct stream position for truncating
tw.Flush();
// Set the stream length to the current position in order to truncate leftover text
fs.SetLength(fs.Position);
}
}
If you use .NET 4.5 or later, there is a new overload which prevents the disposal of the StreamWriter to also dispose the underlying stream. The code could then be written slighly more intuitively like this:
using (FileStream fs = new FileStream(filename, FileMode.Open)) {
using (TextWriter tw = new StreamWriter(fs, Encoding.UTF8, 1024, true)) {
// Write your data here...
tw.WriteLine("foo");
}
// Set the stream length to the current position in order to truncate leftover text
fs.SetLength(fs.Position);
}
By Lucero. Read the original answer on Stack Overflow.
There are two things which can cause the instantiation of a second or subsequent NamedPipeServerStream on the same pipe to fail:
- the maxNumberOfServerInstances ctor argument must have been set to more than 1 when the first instance of the pipe server was created. If not, the second call will fail unless the first instance has already been closed completely.
- the process calling the ctor must have the access right represented by PipeAccessRights.CreateNewInstance. This is a powerful right which the pipe server should guard jealously, as it allows its possessor the ability to act as a pipe server.
The service process should set the pipe security thus:
PipeSecurity ps = new PipeSecurity();
ps.AddAccessRule(new PipeAccessRule(myPipeUsersGroup, PipeAccessRights.ReadWrite, AccessControlType.Allow));
ps.AddAccessRule(new PipeAccessRule(myPipeServerIdentity, PipeAccessRights.FullControl, AccessControlType.Allow));
where:
myPipeUsersGroupis a placeholder for a group which contains all the prospective client identities which will connect to the pipe. Depending on your requirements/use case this might be a specific client identity, a custom group, or a built in group such as "Users" or "Administrators".myPipeServerIdentityis a placeholder for the service identity. This might be set, for example, toWindowsIdentity.GetCurrent().Owner. When the pipe server is hosted in a Windows service, then even better (but a good deal harder to implement) would be the Logon SID identity of the service process - this would ensure that only the specific service process could create instances of the pipe.
If you want to ensure that pipe access is restricted to just users logged on locally i.e. to prevent remote access across a network, you can also add a deny ACE for Network Users into the pipe security ACL.
By Chris Dickson. Read the original answer on Stack Overflow.
Here is my fix for this problem:
I'm using Win 7 64bit and Office 2007
Run program "dcomcnfg -32". ( You cant find the word and excel components if it runs under 64bit)
Go to "Console Root/Component Services/Computer/My Computer/DCOM Config/" Look up Microsoft Word and Excel and choose properties.
Go to Security and select "Customize" under "Configuration Permissions. (If needed you might want to change the other permissions as well, but I didn't need to) Add "IIS_IUSRS" and give it "Full Control".
Now go to "Identity" and select "The interactive user".
Do not forget to press "OK" when done. :D
I Hope this helps you with your problem and also the rest who gets here and read this.
By Tomas I. Read the original answer on Stack Overflow.
I figured it out.
static void Main()
{
PipeSecurity ps = new PipeSecurity();
ps.AddAccessRule(new PipeAccessRule("Users", PipeAccessRights.ReadWrite | PipeAccessRights.CreateNewInstance, AccessControlType.Allow));
ps.AddAccessRule(new PipeAccessRule("CREATOR OWNER", PipeAccessRights.FullControl, AccessControlType.Allow));
ps.AddAccessRule(new PipeAccessRule("SYSTEM", PipeAccessRights.FullControl, AccessControlType.Allow));
ps.AddAccessRule(pa);
using (NamedPipeServerStream pipeServer =
new NamedPipeServerStream("testpipe",PipeDirection.InOut,10,
PipeTransmissionMode.Message, PipeOptions.WriteThrough, 1024,1024,ps))
using (NamedPipeServerStream pipeServer2 =
new NamedPipeServerStream("testpipe", PipeDirection.InOut, 10,
PipeTransmissionMode.Message, PipeOptions.WriteThrough,1024,1024,ps))
{
By adding the rights PipeAccessRights.CreateNewInstance it now works fine.
I hit another snag but i solved it, but wanted to post it in case other people found this through Google. by providing your own Pipe security object it removes the default one, so if you need it you need to re-add the System group so it can talk to the pipe if you are writing a service. I updated my above code to what I used to get a elevated service and a non elevated winforms app to talk to each other (Creator owner is likely unnecessary)
By Scott Chamberlain. Read the original answer on Stack Overflow.
Source: Stack Overflow