skip to Main Content

I want to use the std::filesystem::remove() function to remove a file, and give an error if the file does not exist. Something like this:

std::error_code errorCode;
if (!std::filesystem::remove("<some file path>", errorCode))
{
    std::cout << "Could not delete file because " << errorCode.message();
}

However, if the file does not exist, this yields the message Could not delete file because unknown error.

My question is: Why doesn’t this tell me that the file does not exist?

I interpret the documentation on cppreference to say that

  • The non-error_code version of the remove function returns false if the file does not exist, and throws an exception on other errors.
  • The error_code version returns false on any error, and stores the reason in the error_code. It never throws an exception.

Given that the error code just says "unknown error" when a file does not exist, it seems that this version gives less information than the non-error_code one? Or maybe I’m misunderstanding something?

I’m on Windows 11, using Visual Studio 2022 Version 17.11.2.

2

Answers


  1. The reason std::filesystem::remove() returns "unknown error" on Windows when the file doesn’t exist is due to how some implementations of the standard library handle error codes for missing files. In this case, it may not map the error correctly, resulting in a vague message.

    Solution:
    Check if the error code is std::errc::no_such_file_or_directory, which explicitly represents "file not found":

    std::error_code errorCode;
    if (!std::filesystem::remove("<some file path>", errorCode)) {
        if (errorCode == std::errc::no_such_file_or_directory) {
            std::cout << "File does not exist.n";
        } else {
            std::cout << "Could not delete file because " << errorCode.message();
        }
    }
    

    This works well for me, so probably for you aswell, if it doesn’t work, feel free to ask me 😀

    Login or Signup to reply.
  2. Since you did not tag the question with a specific OS, and want to know the generic answer, I will answer in an opinion-based way.

    The C++ standard library depends on an implementation. Filesystems can vary. Your library implementation might think that "file does not exist" is not an error.

    I do not have a print copy. The below is an extract from the latest draft of C++.

    31.12.13.31 Remove [fs.op.remove]

    bool filesystem::remove(const path& p);

    bool filesystem::remove(const path& p, error_code& ec) noexcept;

    1 Effects: If exists(symlink_status(p, ec)), the file p is removed as if
    by POSIX remove()
    . [Note 1 : A symbolic link is itself removed, rather
    than the file it resolves to. — end note]

    2 Postconditions:
    exists(symlink_status(p)) is false.

    3 Returns: false if p did not
    exist, otherwise true. The signature with argument ec returns false if
    an error occurs.

    You have might noticed that file is removed as if POSIX remove was called. Windows is not POSIX compliant. The Windows implementation of the library might have chosen another way of how to look on file removal.

    update

    To clarify things I think I need to elaborate on my answer a little more. Please consider the below possible implementation of the function.

    bool            exists = false;
    std::error_code e      = 0;
    
    try {
     exists = ... /* check that a file exists */
     if(exists) {
      /* remove the file */
     }
    }catch(...) {
     exists = false;
    }
    
    e = platform_specific_error_code;
    return exists;
    

    The return value error will be the error that platform had set before the return from the above implementation. This possible implementation is done according to standard wording. With my possible implementation you will get error return from the platform. So if you would had chosen my implementation over the implementation that you are using now, you would have get the above results.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search