Skip to content

Fix conan cache restore crashing with PermissionError when the cache contains read-only files - #20254

Open
danimtb wants to merge 4 commits into
conan-io:develop2from
danimtb:danimtb/cache-restore-permissions
Open

Fix conan cache restore crashing with PermissionError when the cache contains read-only files#20254
danimtb wants to merge 4 commits into
conan-io:develop2from
danimtb:danimtb/cache-restore-permissions

Conversation

@danimtb

@danimtb danimtb commented Aug 12, 2026

Copy link
Copy Markdown
Member

Changelog: Bugfix: Fix conan cache restore crashing with PermissionError when the cache contains read-only files.
Docs: Omit

  • Refer to the issue that supports this Pull Request.
  • If the issue has missing info, explain the purpose/use case/pain/need that covers this Pull Request.
  • I've read the Contributing guide.
  • I've followed the PEP8 style guides for Python code.
  • I've opened another PR in the Conan docs repo to the develop branch, documenting this one.

Fixes #20241

There are two different points where this happens, and the second one was only reachable
after fixing the first:

  • tarfile.extractall() opens each destination file in wb mode, which fails when the file
    already exists and is read-only. This is the traceback reported in the issue, and it happens
    when the package folder is restored in place (a package downloaded from a server, or an
    archive restored over the same cache it was saved from).
  • shutil.rmtree() is used to remove a previously restored package/metadata folder when the
    package has to be relocated to a different folder in the destination cache. It has no
    handler for read-only files, so it raises PermissionError: [WinError 5] Access is denied.

The fix makes pre-existing destination files writable before extracting, preserving the rest
of the permission bits so group/other permissions are not dropped on Linux and macOS. Files
keep the mode stored in the archive after extraction, so read-only files stay read-only.

There is a pull-request opened some days ago at #20249 but it misses the second issue mentioned in this one plus some tests that reproduce the issue, so I'd rather open this new one.

@danimtb danimtb added this to the 2.32.0 milestone Aug 12, 2026
@danimtb

danimtb commented Aug 12, 2026

Copy link
Copy Markdown
Member Author

The failing linux tests look unrelated to the changes in this PR https://github.com/conan-io/conan/actions/runs/31588322506/job/94108647641?pr=20254

@danimtb
danimtb requested a review from ErniGH August 14, 2026 09:14
Comment thread conan/api/subapi/cache.py
# Extraction opens the destination for writing, read-only files would fail
dest = os.path.join(cache_folder, member.name)
if member.isfile() and os.path.isfile(dest) and not os.access(dest, os.W_OK):
os.chmod(dest, os.stat(dest).st_mode | stat.S_IWRITE)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't end up with the same permissions it had before. Is this expected?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, this seems to be forcing some permissions that it didn't have before?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The chmod is temporary and only makes the existing destination writable so extractall() can open it. The tarfile then applies the mode stored in the archive member and file ends with the same permissions it had when saved.

I will improve the tests to reflect this, thanks for pointing it out!

Comment thread conan/api/subapi/cache.py
for member in the_tar.getmembers():
# Extraction opens the destination for writing, read-only files would fail
dest = os.path.join(cache_folder, member.name)
if member.isfile() and os.path.isfile(dest) and not os.access(dest, os.W_OK):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change is only applied to the files. Could there be a directory with write-only permissions that ends up causing a similar error?

@AbrilRBS
AbrilRBS self-requested a review August 14, 2026 12:24

@memsharded memsharded left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am not sure about this. If some files are read-only, they are read-only, they cannot be overwritten or changed permissions. It is the responsibility of the user to handle those files.

Comment thread conan/api/subapi/cache.py
# Extraction opens the destination for writing, read-only files would fail
dest = os.path.join(cache_folder, member.name)
if member.isfile() and os.path.isfile(dest) and not os.access(dest, os.W_OK):
os.chmod(dest, os.stat(dest).st_mode | stat.S_IWRITE)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, this seems to be forcing some permissions that it didn't have before?

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[bug] PermissionError during conan cache restore when extracting read-only files on Windows

4 participants