From a302b6d9c23d250d2978172cc3d4b70e3eee08af Mon Sep 17 00:00:00 2001 From: Rebecca Turner Date: Tue, 29 Jul 2025 22:07:01 -0700 Subject: [PATCH] fromfilename: Don't crash if title is missing Prevents this crash: ``` $ beet import ~/Music/Music/_/[1405]/00.mp3 Traceback (most recent call last): File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/bin/.beet-wrapped", line 9, in sys.exit(main()) ~~~~^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/__init__.py", line 1859, in main _raw_main(args) ~~~~~~~~~^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/__init__.py", line 1838, in _raw_main subcommand.func(lib, suboptions, subargs) ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/commands.py", line 1390, in import_func import_files(lib, byte_paths, query) ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/ui/commands.py", line 1330, in import_files session.run() ~~~~~~~~~~~^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/importer/session.py", line 234, in run pl.run_parallel(QUEUE_SIZE) ~~~~~~~~~~~~~~~^^^^^^^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/util/pipeline.py", line 471, in run_parallel raise exc_info[1].with_traceback(exc_info[2]) File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/util/pipeline.py", line 336, in run out = self.coro.send(msg) File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/util/pipeline.py", line 219, in coro func(*(args + (task,))) ~~~~^^^^^^^^^^^^^^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/importer/stages.py", line 141, in lookup_candidates plugins.send("import_task_start", session=session, task=task) ~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/plugins.py", line 505, in send result = handler(**arguments) File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beets/plugins.py", line 200, in wrapper return func(*args, **kwargs) File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beetsplug/fromfilename.py", line 165, in filename_task apply_matches(d, self._log) ~~~~~~~~~~~~~^^^^^^^^^^^^^^ File "/nix/store/lfv9ns20hz2bg6d44js378vcxjfm9261-beets-2.3.1/lib/python3.13/site-packages/beetsplug/fromfilename.py", line 124, in apply_matches item.title = str(d[item][title_field]) ~~~~~~~^^^^^^^^^^^^^ KeyError: 'title' ``` --- beetsplug/fromfilename.py | 2 +- docs/changelog.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/beetsplug/fromfilename.py b/beetsplug/fromfilename.py index 5e8b338c7..7f9e9b92e 100644 --- a/beetsplug/fromfilename.py +++ b/beetsplug/fromfilename.py @@ -121,7 +121,7 @@ def apply_matches(d, log): # Apply the title and track. for item in d: if bad_title(item.title): - item.title = str(d[item][title_field]) + item.title = str(d[item].get(title_field, "")) log.info("Title replaced with: {.title}", item) if "track" in d[item] and item.track == 0: diff --git a/docs/changelog.rst b/docs/changelog.rst index 4dc38da94..67c284a88 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -83,6 +83,8 @@ Bug fixes: the config option ``deezer.search_query_ascii: yes``. :bug:`5860` - Fixed regression with :doc:`/plugins/listenbrainz` where the plugin could not be loaded :bug:`5975` +- :doc:`/plugins/fromfilename`: Beets will no longer crash if a track's title + field is missing. For packagers: