File.Exists returns true after File.Delete

I have the following method to delete a file with a provided path

private void DestroyFile(string path)
{
    try
    {
        if (File.Exists(path))
        {
            File.Delete(path);
        }
        if (File.Exists(path))
        {
            throw new IOException(string.Format("Failed to delete file: '{0}'.", path));
        }
    }
    catch (Exception ex)
    {
        throw ex;
    }
}

I am getting the IOException that is thrown if the file exists after the File.Delete method. Specifically

System.IO.IOException): Failed to delete file: 'C:\Windows\TEMP\[FILE NAME]'.

I have also confirmed that the file does not exist at the location in the path variable after the execution is complete. I am wondering if I am running up against a race condition between the file system updating after File.Delete and checking against it again with File.Exists. Is there a better way to smoothly delete? I know that File.Delete won't return an error if the file doesn't exist so maybe these checks are a bit redundant. Should I check if the file is in use rather than if it exists at all?

Some important additional information: The program can and does run successfully often but this particular error has been frequently seen recently.

File.Delete will mark file for deletion. File really will be deleted only when all handles to it are closed (if there are no such handles - it will always be deleted after File.Delete returns). As documented for DeleteFile winapi function (which is used by C# File.Delete):

The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed

Usually there are no open handles to files you delete. Or, if there are open handles - they usually don't have "delete" share (this share allows another process to mark file for deletion), so when you try to delete such file - it either gets deleted (no open handles) or access denied or similar exception is thrown (some handles, but without delete share).

However, sometimes some software, such as antivirus or search indexer, might open arbitrary files with "delete" share and hold them for some time. If you try to delete such file - it will go without errors and file really will be deleted when that software closes its handle. However, File.Exists will return true for such "pending delete" file.

You can reproduce this issue with this simple program:

public class Program {
    public static void Main() {
        string path = @"G:\tmp\so\tmp.file";
        // create file with delete share and don't close handle
        var file = new FileStream(path, FileMode.Create, FileAccess.ReadWrite, FileShare.Delete);
        DestroyFile(path);
        GC.KeepAlive(file);
    }

    private static void DestroyFile(string path) {
        try {

            if (File.Exists(path)) {
                // no error
                File.Delete(path);
            }
            // but still exists
            if (File.Exists(path)) {
                throw new IOException(string.Format("Failed to delete file: '{0}'.", path));
            }
        }
        catch (Exception ex) {
            throw ex;
        }
    }
}

You can retry File.Exists check forever in the program above - file will exist until you close the handle.

So that's what happens in your case - some program has open handle to this file with FileShare.Delete.

You should expect such situation. For example - just remove that File.Exists check, since you marked file for deletion and it will be deleted anyway.

java file.delete() returns false but file.exists() returns true, When I am trying to delete a file which is present in tomcat server conf/Catalina/​localhost from java code then file.delete() always returns false. When the program is ended, from inside <anonymous WindowListener>.windowClosing() a method is called that should delete the files. but they dont get deletet. delete() returns false, and exists() returns true. Even if I request deleteOnExit() on that files, they aren't deleted.

while its not documented in the API, File.Delete WILL return before the file is completely deleted.

This is why you are running into the case you are having. Delete call will check for all the things that would make the delete fail (existing handle, lock, permission ect) and it will return after the initiation of Delete request

So its relatively safe to just put a while loop right after to wait until the file is gone or use a FileSystemWatcher to watch for Deleted event

File.exists() returns true (I/O and Streams forum at Coderanch), Sometimes it takes a little while before the file system cache catches up with operations. So if you call exists() right after delete(), it might return  VBScript » FileSystemObject » FileExistsVersion: 2.0 Syntax: object.FileExists(file)Lets us check whether a specified file exists. Returns True if the file does exist and False otherwise.Note that if the file that you are checking for isn't in the current directory, you must supply the complete path.

File.Delete and generally most methods from System.IO are dependent on filesystem/streams/etc, whom a bit live their own lives, and are not managed resources, hence File.Delete can return before file is physically deleted, but after it's marked for deletion.

After File.Delete returns, you can be sure file will be deleted, if not this method will throw exception by itself, so second check with File.Exists and throwing IOException is unnecessary.

If you want custom exception, catch exceptions from File.Delete.

And in code attached, remember that throw ex; is diffrenent from throw; and changes stack trace to current line.

File.exists() returns true for non-existent files? : javahelp, I've deleted the file that I am trying to create and its preceding directory. Before I even call the 'createNewFile()' method I check to see if the File exists. But since the data the client is sending is large, it is exceeding 60sec time frame and  The file _ exists function returns TRUE if the file or directory specified by filename exists; FALSE otherwise. Syntax of file _ exists () Function PHP bool file _ exists ( file _name ) It test the existence of the file

Delete a file using Java, public boolean delete() Returns: true if and only if the file or directory is successfully Using java.nio.file.files.deleteifexists(Path p) method defined in Files  true if the caller has the required permissions and path contains the name of an existing file; otherwise, false.This method also returns false if path is null, an invalid path, or a zero-length string.

Files deleteIfExists() method in Java with Examples, Files help us to delete a file if the file exists at the path. we pass the path of This method will return true if the file was deleted by this method; false if the After deleting the file: The file is deleteIfExistsd from the path “D:\\Work\\Test\\file1.txt”. The actual problem is a stale NFS file handle, which can occur for a number of reasons. An examination of the java source code shows that File.exists ends up performing a stat(2). If the stat fails, then File.exists assumes that the file being stat'ed does not exist. This is a false assumption. stat(2) can fail for several reasons other than ENOENT.

Java.io.File.exists() Method, File.exists() method tests the existence of the file or directory defined by this abstract The method returns boolean true, if and only if the file defined by the abstract System.out.println("File exists: "+bool); if(bool == true) { // delete() invoked  The java.io.File.exists() method tests the existence of the file or directory defined by this abstract pathname. Declaration. Following is the declaration for java.io.File.exists() method − public boolean exists() Parameters. NA. Return Value. The method returns boolean true, if and only if the file defined by the abstract pathname exists

Comments
  • This statement... I have also confirmed that the file does not exist at the location in the path variable after the execution is complete. ...contradicts the possibility of this... I am wondering if I am running up against a race condition between the file system updating after File.Delete and checking against it again with File.Exists. I strongly suspect something is creating the file after you made your call to Delete().
  • I thought that C:\Windows is a locked directory. An application must be admin to delete. Also with it being in a Windows directory, it is possible that something is using the file.
  • @Greg I looked into permissions and I can rule that out. It might be an important detail that the method does work some of the time
  • @JᴀʏMᴇᴇ To clarify, I'm saying that maybe a cache hasn't fully updated after the File.Delete so the file still exists in some capacity when the File.Exists check comes through. I am using the GetTempFileName() method to create the temp files though no arguments are passed. I wonder if that could lead to a re-use of file names and thus the issue you've brought up.
  • Wow, this is absolute insanity. Thanks for the heads-up. Assuming you're in an async method, following your delete with this line will wait until the file is actually deleted before continuing on: while (File.Exists(path)) await Task.Delay(100);
  • @Grinn thing is there is rarely reason to do that. File will be deleted when last handle is closed so you can just move on. Unless you want to create another file instead of deleted, but in this case just overwrite contents without deletion.
  • I agree. In my case I have an app that has multiple threads each flagging the file paths they are processing while they are being processed, then deleting them prior to unflagging the path. On rare occasions, files were being unflagged before physically removed from the drive due to the circumstances you outlined. This resulted in unexpected behavior because other threads would pick up the file in question. So, thanks!