-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Safely handle metadata plugin exceptions. #5965
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
This comment was marked as resolved.
This comment was marked as resolved.
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #5965 +/- ##
==========================================
+ Coverage 66.47% 66.54% +0.06%
==========================================
Files 117 117
Lines 18105 18124 +19
Branches 3071 3073 +2
==========================================
+ Hits 12036 12061 +25
+ Misses 5414 5408 -6
Partials 655 655
🚀 New features to boost your workflow:
|
Related:
|
ad7319f
to
cbf389c
Compare
cbf389c
to
88741c3
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Overview
This PR adds exception handling to metadata plugin operations to prevent crashes during the auto-tagger process. When individual metadata plugins encounter errors, the system will now log the issues and continue processing with other available metadata sources instead of failing completely.
- Introduces safe wrapper functions (
_safe_call
and_safe_yield_from
) around metadata plugin method calls - Updates all plugin interface methods to use exception handling
- Adds comprehensive test coverage for error scenarios in metadata plugins
Reviewed Changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
File | Description |
---|---|
beets/metadata_plugins.py | Core implementation of exception handling with safe wrapper functions and updated plugin interface calls |
test/test_metadata_plugins.py | New test file with mock error plugin and comprehensive test coverage for all metadata plugin methods |
docs/changelog.rst | Documentation of the bug fix in the changelog |
Tip: Customize your code reviews with copilot-instructions.md. Create the file or learn how to get started.
Reviewer's GuideThis PR implements robust exception handling around metadata plugin calls by introducing safe-call and safe-yield helpers with logging, updating all plugin invocations to use these wrappers, refining related type signatures, and adding tests and a changelog entry to validate and document the new behavior. Flow diagram for exception handling in plugin callsflowchart TD
A["AutoTagger calls plugin method"] --> B{Exception raised?}
B -- Yes --> C["Log error"]
C --> D["Continue to next plugin"]
B -- No --> E["Process plugin result"]
E --> D
File-Level Changes
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey there - I've reviewed your changes - here's some feedback:
- The log.error calls use curly-brace placeholders but Python’s logging module expects %-style formatting or preformatted strings—update them to use %s or f-strings so the plugin name and exception actually interpolate.
- As mentioned in the PR limitations, consider adding a config flag to let users opt in to failing on plugin exceptions instead of always swallowing errors.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The log.error calls use curly-brace placeholders but Python’s logging module expects %-style formatting or preformatted strings—update them to use %s or f-strings so the plugin name and exception actually interpolate.
- As mentioned in the PR limitations, consider adding a config flag to let users opt in to failing on plugin exceptions instead of always swallowing errors.
## Individual Comments
### Comment 1
<location> `test/test_metadata_plugins.py:63` </location>
<code_context>
+ with caplog.at_level("ERROR"):
+ # Call the method to trigger the error
+ ret = getattr(metadata_plugins, method_name)(*args)
+ if isinstance(ret, Iterable):
+ list(ret)
+
</code_context>
<issue_to_address>
Test does not verify that normal (non-error) plugins still work alongside error-raising plugins.
Add a test that registers both an error-raising and a normal plugin to confirm that exceptions in one do not affect the results from others.
</issue_to_address>
### Comment 2
<location> `test/test_metadata_plugins.py:67` </location>
<code_context>
+ list(ret)
+
+ # Check that an error was logged
+ assert len(caplog.records) == 1
+ logs = [record.getMessage() for record in caplog.records]
+ assert logs == ["Error in 'ErrorMetadataMockPlugin': Mocked error"]
</code_context>
<issue_to_address>
Test only checks for error-level logs, but does not verify that debug-level logs (with exception details) are emitted.
Please add assertions to check that debug-level logs with exception details are present, ensuring complete error context is captured.
</issue_to_address>
### Comment 3
<location> `test/test_metadata_plugins.py:69` </location>
<code_context>
+ # Check that an error was logged
+ assert len(caplog.records) == 1
+ logs = [record.getMessage() for record in caplog.records]
+ assert logs == ["Error in 'ErrorMetadataMockPlugin': Mocked error"]
+ caplog.clear()
</code_context>
<issue_to_address>
Test only checks for a single error log per method call, but does not verify that repeated calls do not accumulate unexpected logs.
Add a test to confirm that multiple calls to the method do not produce extra or unexpected log entries.
</issue_to_address>
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
It does feel like we should pause the import until the user has acknowledged the issue (maybe providing options to skip importing the album or continue with existing metadata?), as otherwise you could end up with missing metadata that is awkward to fix later if for example you had network issues or the provider was down. Not sure how this should interact with |
A prompt makes sense in theory, but I'm really hesitant to add any user interaction because it breaks headless scripts, automation, and make monkey-patching way harder which is a big part of my beets use case. Instead, I'm leaning towards adding a simple config option that lets you tell the plugin to just fail hard if it runs into trouble, so your import would stop and you'd know right away. On a practical level, I'm also not convinced that skipping these errors is a major issue in the first place. The plugin's job is to suggest |
Description
When a metadata plugin raises an exception during the auto-tagger process, the entire operation crashes. This behavior is not desirable, since metadata lookups can legitimately fail for various reasons (e.g., temporary API downtime, network issues, or offline usage).
This PR introduces a safeguard by adding general exception handling around metadata plugin calls. Instead of causing the whole process to fail, exceptions from individual plugins are now caught and logged. This ensures that the auto-tagger continues to function with the remaining available metadata sources.
This replaces the efforts from #5910
Limitations
Sometimes one might not want to continue if an exception is encountered a metadata plugin. Do we need/want a config option to raise if an issue is encountered?
Summary by Sourcery
Wrap all metadata plugin calls in safe handlers to prevent individual plugin failures from aborting the auto-tagging process, update plugin interfaces, add comprehensive error logging, and include tests and a changelog entry.
Bug Fixes:
Enhancements:
Documentation:
Tests: