Skip to content

Fix importfeeds to continue on symlink creation failures#6765

Open
sammydynamo-dev wants to merge 7 commits into
beetbox:masterfrom
sammydynamo-dev:fix-issue-840
Open

Fix importfeeds to continue on symlink creation failures#6765
sammydynamo-dev wants to merge 7 commits into
beetbox:masterfrom
sammydynamo-dev:fix-issue-840

Conversation

@sammydynamo-dev

@sammydynamo-dev sammydynamo-dev commented Jun 23, 2026

Copy link
Copy Markdown

Description

Fixes #840.

When importfeeds is configured with formats: link, it creates a symlink for each imported track. If that symlink can't be created — on Windows without the privilege to make symlinks (the original report), but also on any OS when the destination directory isn't writable or the filesystem doesn't support symlinks — beets.util.link() raises FilesystemError. That exception wasn't caught, so it propagated out of the import pipeline and aborted the entire beet import run, even though the tracks had already been imported into the library.

This wraps the link() call in ImportFeedsPlugin._record_items() in try/except FilesystemError, logs a per-item warning, and continues with the remaining items — so a failed symlink is skipped rather than fatal. This is the "catch and skip" behaviour suggested in the issue thread. It catches FilesystemError (not OSError, which util.link() wraps) and mirrors the existing handling in beetsplug/playlist.py and the fetchart fix (#6193).

Adds five regression tests (warn-and-continue, that remaining items are still linked, that only FilesystemError is caught, and that a successful link still creates the symlink). Also verified manually: with a read-only feeds directory, beet import now finishes with a warning (exit 0) instead of aborting (exit 1), and the track is still imported.

To Do

  • Documentation (bugfix; no user-facing flag or config changed)
  • Changelog
  • Tests

sammydynamo-dev and others added 2 commits June 23, 2026 02:04
When `formats` includes `link`, importfeeds creates a symlink per imported
item. A failed symlink (lacking privilege on Windows, a read-only directory, or
a filesystem without symlink support) raised beets.util.FilesystemError out of
the import pipeline and aborted the whole `beet import` run, even though the
tracks were already imported.

Catch FilesystemError around the link() call, log a per-item warning, and
continue with the remaining items. Add regression tests for the
warn-and-continue behaviour, that only FilesystemError is caught, and that a
successful link still creates the symlink.

Fixes beetbox#840.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot added the importfeeds importfeeds plugin label Jun 23, 2026
@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.81%. Comparing base (c90f42d) to head (75e6724).
✅ All tests successful. No failed tests found.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #6765      +/-   ##
==========================================
+ Coverage   74.78%   74.81%   +0.03%     
==========================================
  Files         163      163              
  Lines       20966    20969       +3     
  Branches     3302     3302              
==========================================
+ Hits        15680    15689       +9     
+ Misses       4529     4523       -6     
  Partials      757      757              
Files with missing lines Coverage Δ
beetsplug/importfeeds.py 86.25% <100.00%> (+5.73%) ⬆️

... and 1 file with indirect coverage changes

🚀 New features to boost your workflow:
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@sammydynamo-dev sammydynamo-dev marked this pull request as ready for review June 23, 2026 10:27
@sammydynamo-dev sammydynamo-dev requested a review from a team as a code owner June 23, 2026 10:27
@sammydynamo-dev sammydynamo-dev marked this pull request as draft June 24, 2026 23:47
@sammydynamo-dev sammydynamo-dev marked this pull request as ready for review June 24, 2026 23:54
@sammydynamo-dev

Copy link
Copy Markdown
Author

Hi @snejus 👋 — this is my first contribution to beets.

This PR (#6765) fixes #840: when importfeeds is set to formats: link and a
symlink can't be created (e.g., on Windows, or into a read-only directory), the Failure is now logged as a per-item warning, and the import continues, instead of
The unhandled FilesystemError aborted the whole beet import run. It follows
the same warn-and-skip pattern as the fetchart fix (#6662) and playlist.py.

It includes five regression tests and a changelog entry, and the full test suite
passes locally. I tagged you since you reviewed the very similar fetchart change —
No rush at all, but I'd appreciate a review whenever you have time. Thanks!

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

Labels

importfeeds importfeeds plugin

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ImportFeeds: fix/disable/catch symlink usage on windows

1 participant