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 <module>
    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'
```
This commit is contained in:
Rebecca Turner 2025-07-29 22:07:01 -07:00 committed by Sebastian Mohr
parent 3336b68d08
commit a302b6d9c2
2 changed files with 3 additions and 1 deletions

View file

@ -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:

View file

@ -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: