Sitelet https://github.com/nodejs/node/issues/64374
Skip to content

fs.rmSync cannot remove read-only files on Windows when Node is built with libc++ #64374

Description

@nmggithub

Version

No response

Platform


Subsystem

No response

What steps will reproduce the bug?

Use fs.rmSync on a read-only file on Windows.

How often does it reproduce? Is there a required condition?

Note, this issue appears to only exhibit in Electron, but that is due to our specific build configuration (more at the bottom of this issue).

Downstream issue: electron/electron#52253

What is the expected behavior? Why is that the expected behavior?

Read-only files should be able to be removed with rmSync. This has worked previously.

What do you see instead?

As per downstream issue, the call fails with EPERM.

Additional information

Since #53617, the implementation for fs.rmSync has been written in C++ (specifically using std::filesystem::remove). However, depending on the C++ stdlib being used, this leads to divergent behavior.

  1. The MSVC STL, used by official Node builds, specifically includes code to support the removal of read-only files with filesystem::remove.
  2. libc++, currently, does not have such code and uses an API that does not support the removal of read-only files.

Electron uses libc++ to build Node, so it encounters this divergent behavior. Should Node handle this inconsistency inside RmSync, or should libc++ be aligned with the behavior of the MSVC STL?

Activity

  1. added
    windowsIssues and PRs related to the Windows platform.
    fsIssues and PRs related to file-system APIs and the fs module.
    on Jul 12, 2026
  2. SparshGarg999 commented on Jul 12, 2026

    @SparshGarg999
    Contributor

    Hi! I've implemented a fix for this in PR #64453.

    I added a Windows-specific helper ClearReadOnlyAttributeW in src/node_file.cc that is invoked if the standard std::filesystem::remove or std::filesystem::remove_all fails with std::errc::operation_not_permitted (EPERM).

    On Windows, libc++'s filesystem implementation does not clear the FILE_ATTRIBUTE_READONLY attribute before deleting a file (unlike MSVC's STL which does). My helper manually detects if the read-only attribute is present, clears it recursively (or for a single file/symlink), and retries the removal operation.

    This brings Node.js builds compiled under libc++ (such as Electron) to parity with standard MSVC STL builds.

    I verified the fix with a new test case in test/parallel/test-fs-rm.js targeting read-only file/directory removal, and confirmed that all code style (cpplint / eslint) rules pass cleanly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    fsIssues and PRs related to file-system APIs and the fs module.windowsIssues and PRs related to the Windows platform.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions