beetbox / beetbox/beets

importadded: PermissionError thrown when converting from a readonly source

Open Beginner friendly
#6,954 0 comments 0 reactions 0 assignees View on GitHub
importadded
Dominant language
Python
Stars
15.7k
Forks
2.1k
Avg merge
4d 21h
Merged PRs (30d)
31

Description

### Problem

To avoid messing up my extensive flac collection, I have a cron job setting up the immutable flag on flac files that are older than X days. In the rare case where I have to retag old music with beets I'd then `chattr -i` the relevant files.

I have the importadded plugin enabled with both preserve_mtimes' and 'preserve_write_mtimes' set to 'yes'.

Today I needed to reconvert old files, so I ran `beet convert -y` on albums that had the immutable bit set; my assumption was that beets/importadded wouldn't need write permission to the original flac files, but it threw the following exception:

```
File "/home/user/.local/lib/python3.14/site-packages/beetsplug/importadded.py", line 149, in update_after_write_time
self.write_item_mtime(item, item.added)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^
File "/home/user/.local/lib/python3.14/site-packages/beetsplug/importadded.py", line 86, in write_item_mtime
self.write_file_mtime(util.syspath(item.path), mtime)
~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/user/.local/lib/python3.14/site-packages/beetsplug/importadded.py", line 79, in write_file_mtime
os.utime(util.syspath(path), (stat.st_atime, mtime))
~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
PermissionError: [Errno 1] Operation not permitted: '/01 somename.flac'
```

So - for some reason, importadded wants to write to the original flac file despite not needing it.

Looking at beetsplug/importadded.py, function `update_after_write_time(self, item, path)` actually doesn't use the 'path' argument and forcibly sets the time on 'item', rather than 'path' (which IIUC is the file that was just converted). So it seems that the right way would be to set the mtime on 'path' rather than 'item'. Replacing `self.write_item_mtime(item, item.added)` by the following fixed the issue:

```
self.write_file_mtime(util.syspath(path), item.added)
# update item.mtime only when 'path' is the item's own file, not a converted file
if path == item.path:
item.mtime = item.added
```

(It may be the wrong fix though, I'm not familiar with beets' code - so I'm not opening a PR)

### Setup

* OS: fedora 44
* Python version: 3.14.7
* beets version: 2.13.1 (but I checked the code of importadded - it's the same as in the current 'main' branch)

Contributor guide

Open the contributing guide

Research direction

Start in beetsplug/importadded.py, especially update_after_write_time, write_item_mtime, and write_file_mtime, and reproduce the issue with beet convert -y on an immutable source file. Confirm that conversion no longer attempts to modify the original file and that the intended modification time is applied to the converted path.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cli
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.