Skip to content

Fix folder watch crash on a media path that cannot be read - #1653

Merged
raivisdejus merged 1 commit into
chidiwilliams:mainfrom
Dev-next-gen:fix/folder-watch-stat-vanished-file
Oct 16, 2026
Merged

raivisdejus merged 1 commit into
chidiwilliams:mainfrom
Dev-next-gen:fix/folder-watch-stat-vanished-file

Conversation

@Dev-next-gen

Copy link
Copy Markdown
Contributor

A watch folder that holds a dangling symlink with a media extension stops folder watch. I dropped a single dangling.mp3 symlink pointing at a file that does not exist into the watched folder and called find_tasks():

File "buzz/widgets/transcription_task_folder_watcher.py", line 74, in find_tasks
    os.path.getsize(file_path),
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/tmpvotx26pu/dangling.mp3'

os.walk returns names without stating them, and the duplicate check added in #1556 calls os.path.getsize and os.path.getmtime on every candidate path. Python builds the right hand tuple before comparing it, so the stat runs even for a path that was never emitted. The same two unguarded calls run again after task_found.emit, there after the model download, which can take minutes. Since find_tasks is the slot connected to directoryChanged, the exception ends the scan and nothing listed after the unreadable path gets queued.

A symlink is just the deterministic way to trigger it. The same stat fails when a file is deleted between the scan and the check, which is routine with "delete processed files" on, or on a network folder.

This takes the stamp once, guarded, and skips the file when it cannot be read. The stamp is reused when recording the emitted path, so the second pair of stat calls is gone as well. The duplicate check itself is unchanged, and I confirmed an mp3 already recorded in paths_emitted with its current size and mtime is still skipped.

I proved it by calling the real find_tasks() on a folder holding only the dangling symlink: it raises FileNotFoundError before the change and completes without emitting a task after it. The added test does the same and skips itself on platforms that cannot create symlinks.

Found by a defect-hunting pipeline I build and run (Dev-next-gen), using Claude Code with Anthropic's Claude Opus 5.

find_tasks() stats every candidate file to build its size+mtime stamp, but
os.walk lists names without stating them. A dangling symlink with a media
extension, or a file removed since the scan started, makes os.path.getsize
raise FileNotFoundError and aborts the whole scan, so no later file in the
folder is queued.

Take the stamp once, guarded, and skip the file when it cannot be read.
@raivisdejus
raivisdejus enabled auto-merge (squash) October 16, 2026 17:02
@raivisdejus

Copy link
Copy Markdown
Collaborator

@Dev-next-gen Thanks for your contribution. Seems you have created a good tool to find issues!

@codecov

codecov Bot commented Oct 16, 2026 •

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 83.53%. Comparing base (851c8b3) to head (b4e2291).

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1653      +/-   ##
==========================================
- Coverage   83.56%   83.53%   -0.03%     
==========================================
  Files         116      116              
  Lines       13845    13851       +6     
==========================================
+ Hits        11569    11571       +2     
- Misses       2276     2280       +4     
Flag Coverage Δ
Linux 82.80% <100.00%> (-0.01%) ⬇️
macOS 83.25% <100.00%> (-0.08%) ⬇️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@Dev-next-gen

Copy link
Copy Markdown
Contributor Author

The red build (macos-latest) here fails in the Bundle step before anything from this PR is built: the signing secrets are empty for a fork PR, so the certificate import stops with security: SecKeychainItemImport: Unable to decode the provided data. (job). The same job is also red on the base commit 851c8b3 on main, there at notarization with HTTP status code: 403. A required agreement is missing or has expired. (job), so neither failure comes from the folder watcher change. test (ubuntu-latest), which runs the added test, passed.

Found by a defect-hunting pipeline I build and run (Dev-next-gen), using Claude Code with Anthropic's Claude Opus 5.5.

@raivisdejus

Copy link
Copy Markdown
Collaborator

Yes, Macos Build failure is the expected behavior

@raivisdejus
raivisdejus merged commit d05a48a into chidiwilliams:main Oct 16, 2026
14 of 16 checks passed
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.

2 participants