question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Please don't abort the entire task when a file is missing

See original GitHub issue

Problem

I just enabled the bucket plugin and moving one directory at a time like this:

cd 2/
for x in * ;do beet move artist:"$x"; done

When beets traverses the individual artist directories and stumble upon an album with a missing track, the entire task is aborted. I would rather have beets complain and move on to the next album in the directory instead of simply bailing out:

Moving 13 items (3 already in place).
Error: No such file or directory while moving /mnt/music8/+TAGGED/2/2113 Pritt/2113 Pritt │2020│ Wrist Game 101 [MP3]/04 Ball 2.0.mp3 to /mnt/music8/+TAGGED/0-9/2113 Pritt/2113 Pritt │2020│ Wrist Game 101 [MP3]/04 Ball 2.0.mp3
Moving 40 items (19 already in place).
Error: No such file or directory while moving /mnt/music8/+TAGGED/2/213/213 │2004│ The Hard Way [CD, MP3]/01 Intro.1.mp3 to /mnt/music8/+TAGGED/0-9/213/213 │2004│ The Hard Way [CD, MP3]/01 Intro.mp3
Moving 24 items (5 already in place).
Error: No such file or directory while moving /mnt/music8/+TAGGED/2/21 Savage/21 Savage │2018│ I Am  I Was [CD, MP3]/06 1.5.mp3 to /mnt/music8/+TAGGED/0-9/21 Savage/21 Savage │2018│ I Am  I Was [CD, MP3]/06 1.5.mp3

The missing tracks are (mostly) files I have deleted like this:

find . -type f -regextype awk -iregex '.+[.][0-9][.](mp3|flac|jpg|m3u|ogg|m4a)' -delete

because they are duplicates and leftovers from previous imports.

Now, I know that I’m supposed to run a

beet update to reflect deleted files, however, I’ve had bad experiences with that in the past so I’m a bit nervous to do so again: https://github.com/beetbox/beets/discussions/3973

Setup

  • OS: Linux 5.19.6
  • Python version: 3.9.4
  • beets version: 1.5.0
  • Turning off plugins made problem go away (yes/no): well, no

My configuration (output of beet config) is:

# vim:synmaxcol=500:expandtab:fdm=marker:fdl=0:
#      ${HOME}/etc/beets/config.yaml
#   ‗‗‗‗‗‗‗‗‗‗‗‗ ‗‗‗‗‗‗ ‗‗‗‗‗‗‗‗ ‗‗‗‗‗‗‗‗‗‗‗
#         owner  Magnus Woldrich <m@japh.se>
#         btime  2021-05-13 10:31:39
#         mtime  2021-05-31 16:38:07
#   permissions  You are free to use things you may find useful here.
#                Please improve and share.
#           git  http://github.com/trapd00r/configs/  (up-to-date)
#           url  http://japh.se
#           irc  japh@irc.libera.chat #vim #perl #beets
#   ‗‗‗‗‗‗‗‗‗‗‗‗ ‗‗‗‗‗‗‗‗‗‗‗‗‗ ‗‗‗‗ ‗‗‗‗ ‗‗‗‗

#< what does it look like
## Alanis Morissette │2020│ Reckoning [Single, WEB, MP3]
## Alanis Morissette │2020│ Such Pretty Forks in the Road [WEB, FLAC]
## Anna Ternheim │2003│ My Secret [EP, CD, MP3]
## Anna Ternheim │2004│ Somebody Outside [CD, MP3]
## Anna Ternheim │2005│ Shoreline EP [EP, CD, MP3]
##  ├── 01 Shoreline (radio Version).mp3
##  ├── 02 Little Lies.mp3
##  ├── 03 China Girl.mp3
##  ├── 04 When Tomorrow Comes.mp3
##  ├── 05 Anywhere I Lay My Head.mp3
##  └── cover.jpg

## A/Anna Ternheim/Anna Ternheim │2003│ My Secret [EP, CD, MP3]
#   '- 01 My Secret.mp3
#   '- 02 All For Me.mp3
#   '- 03 A Voice To Calm You Down.mp3
#   '- 04 I Say No (gotland Version).mp3
#   '- 05 Wedding Song (demo Version).mp3
#   '- cover.jpg
#>

#< core options
directory:  /mnt/music8/+TAGGED
library:    ~/var/beets/beets202105.db
pluginpath: /usr/lib/python3.9/site-packages/beetsplug/

# files matching these patterns are deleted from source after import
clutter: ["Thumbs.DB", ".DS_Store", ".m3u", ".pls",
          ".jpg", ".nfo", ".txt", ".log", ".gif",
         ]

replace:
    '[\\]': ''
    '[_]': '-'
    '[/]': '-'
    '^\.': ''
    '[\x00-\x1f]': ''
    '[<>:"\?\*\|]': ''
    '\.$': ''
    '\s+$': ''
    '^\s+': ''
    '^-': ''

ignore: [".*", "*~", "System Volume Information"]

art_filename:          cover # cover.jpg
#asciify_paths:         yes
format_item:           $path
per_disc_numbering:    false
sort_album:            path+
sort_case_insensitive: yes
sort_item:             path+
threaded:              yes
timeout:               5.0
verbose:               no

# <importer
import:
  languages:        en
  write:            yes
  default_action:   apply
#  remove causes a crash: https://github.com/beetbox/beets/issues/716
  duplicate_action: keep
  non_rec_action:   ask
  autotag:          yes
  move:             yes
#  quiet_fallback:   asis # when using the -q flag
  quiet_fallback:   skip # when using the -q flag

  # Either yes or no, controlling whether imported directories are recorded
  # and whether these recorded directories are skipped. This corresponds to
  # the -i flag to beet import.
  incremental:      yes
#>
#< plugins
#plugins: [ # mosaic
#  'fetchart',   'discogs',  'fromfilename', 'inline',     'smartplaylist',
#  'ftintitle',  'info',     'lastgenre',    'lastimport', 'thumbnails',
#  'mpdupdate',  'mpdstats', 'rewrite',      'duplicates', 'missing',
#  'extrafiles', 'edit',     'lyrics',       'mpdqueue',
#]

plugins: [
  'bucket',
  'discogs',
  'duplicates',
#  'edit',
#  'extrafiles',
  'fetchart',
  'fromfilename',
  'ftintitle',
  'info',
  'inline',
  'lastgenre',
  'lastimport',
#  'lyrics', # takes forever
#  'missing',
#  'mpdqueue',
#  'mpdstats',
  'mpdupdate',
  'rewrite',
#  'smartplaylist', # only run it once in a while
]


bucket:
  bucket_alpha:
  - '#-!'
  - '0-9'
  - 'A'
  - 'B'
  - 'C'
  - 'D'
  - 'E'
  - 'F'
  - 'G'
  - 'H'
  - 'I'
  - 'J'
  - 'K'
  - 'L'
  - 'M'
  - 'N'
  - 'O'
  - 'P'
  - 'Q'
  - 'R'
  - 'S'
  - 'T'
  - 'U'
  - 'V'
  - 'W'
  - 'X'
  - 'Y'
  - 'Z'
  bucket_alpha_regex:
    '#-!': ^[^0-9a-zA-ZåÅäÄöÖ]
  bucket_year: []
  extrapolate: no

bpd:
  host: 127.0.0.1
  port: 6601

edit:
  itemfields: track title artist album year
  albumfields: track title artist albumartist album year

extrafiles:
  patterns:
    single_tracks:
      - '+tracks/'
      - '_tracks/'
    single_live:
      - '_live'
      - '+live'
  paths:
    single_tracks: $artist/+tracks
    single_live: $artist/+live


rewrite:
  album .*Sommar i P1:               P1 Sommar
  album .*Sommar och Vinter i P1.*:  P1 Sommar
  album Söndagsintervjun:            P1 Söndagsintervjun
  album .*Musikguiden i p3:          P3 Musikguiden
  album Jukeboxen i p4:              P4 Jukeboxen
  album Musikspecial i p4:           P4 Musikspecial
#  albumartist Various Artists:       VA
  artist Pst.q:                     Pst-q
  artist 10,000 Maniacs:            10000 Maniacs
  artist Fronda.*:                   Fronda
  artist Magnus Rytterstam.*:        Magnus Rytterstam
  artist 江海迦:                     Aga
  artist Whoo Kid:                   DJ Whoo Kid
  artist Looptroop.*:                Looptroop
  artist T.R:                        Öris
  artist Organismen:                 Organism 12
  artist Gms.*:                      GMS
  artist (tupac|2[pP]ac).*:          2pac
  artist .*weird Al.*:               Weird Al Yankovic
  artist .*Green Lantern.*:          DJ Green Lantern
  artist .ingenting.:                Ingenting
  artist Sin[eé]ad O.Connor.*:       Sinéad O'Connor
  artist .*Suzanne.*Vega:            Suzanne Vega
  artist .*1[23]00 mic.*:            1200 Micrograms
  artist elin (ruth)? sigvardsson:   Elin Sigvardsson
  artist elin ruth:                  Elin Sigvardsson
  artist ^Game$:                     The Game
  artist ^Ken$:                      Ken Ring
  artist Special D:                  Special D.
  artist Danne W.*:                  Sjätte Sinnet
  artist Sjatte Sinnet:              Sjätte Sinnet
  artist Ante Barazza:               Sjätte Sinnet

mpd:
  host: localhost
  port: 6600
#  music_directory: /mnt/music8

thumbnails:
  auto: yes # default

lastfm:
  user: betbot

lastgenre:
  auto: yes # default
  canonical: yes
  force: no
  source: artist

ftintitle:
  auto: yes # default

smartplaylist:
# it's better to set save_absolute_paths_in_playlist option in mpd.conf
#  relative_to: ~/mp3/
  playlist_dir: ~/mp3/_playlists
  playlists:
    - name: '+all.m3u'
      query: ''

    - name: 'eminem.m3u'
      query: 'artist:Eminem'

#    - name: 'sm %lower{$genre}.m3u'
#      query: ''

    - name: '$year.m3u'
      query: 'year::(199[0-9]|200[0-9]|201[0-9])'

    - name: '+decent.m3u'
      query: 'play_count:1..'

    - name: '+wow.m3u'
      query: 'play_count:5..'

    - name: 'psychedelic'
      query: 'genre:psychedelic'
    - name: 'loved.m3u'
      query: 'loved:1'

musicbrainz:
  searchlimit: 10

missing:
  format: "$path"

lyrics:
  auto: yes
#  fallback: ''

fetchart:
  auto: yes
  sources: coverart itunes amazon albumart wikipedia google

embedart:
  auto: yes
#>
#< path setup
aunique:
  disambuguators: media mastering label catalognum albumdisambig releasegroupdisambig

match:
  preferred:
    media: ['CD', 'Digital Media|File', 'Vinyl']

paths:
#    mb_trackid::^$:              +unmatched/
# https://www.japh.se/2021/05/23/custom-beet-path-rules-for-record-labels.html
#    label:8bitpeoples:           8/8bitpeoples/%if{$hasyear,${year}} %title{$albumartist} - %title{$album}/${padded_tracknr} %title{$title}
    tag:8bitpeoples:             0-9/8bitpeoples/%if{$hasyear,${year}} $first_artist - %title{$album}/${padded_tracknr} %title{$title}
    label:whoa.nu:               W/Whoa.nu/$base_name
    label:rap_swe:               +swe_hiphop/$base_name
    label:randombastards:        R/Randombastards/$base_name
    label:Norrköping:            S/Sjätte Sinnet/+tracks/$base_name
    tag:rosamannen:              +live/$artist - $album/$base_name
#    tag:Rosamannen:              +live/+rosamannen/$base_name
    label:frizon.info:           F/Frizon.info/$base_name
    label:"Masters of Hardcore": M/Masters of Hardcore/$moh_catalog %if{$hasyear,${year}} %title{$album}/${padded_tracknr} %title{$artist} - %title{$title}
    label:gamesoundtrack:        +game/+ost/$album%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
    label:ocremix:               +game/+ocremix/$base_name
    tag:overlooked:              +game/+overlookedremix/$base_name
    label:amigaremix:            +game/+amigaremix/$base_name
#    tag:gamealbums:            +game/$first_artist - %title{$album}%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
    tag:gamealbums:            +game/%title{$album} [$albumartist]%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
#    label:gamealbums:            +game/$first_artist - %title{$album}%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
    label:game:                  +game/+tracks/$base_name
    tag:sr:                      +radio/Sveriges Radio/%title{$album}/%title{$title}
#    label:radio:                 +radio/%title{$first_artist}/%title{$album}/%title{$title}
    label:demo:                  %bucket{$first_artist, alpha}/%title{$first_artist}/+demo/$base_name
    label:live:                  %bucket{$first_artist, alpha}/%title{$first_artist}/+live/%title{$albumartist}%if{$hasyear, │${year}│} %title{$album} [$alb_type$media_type$format]/${padded_tracknr} %title{$title}
#    label:test:                  +test/%title{$artist}/%title{$album}/%title{$title}
#    albumtype:mixtape:           +mixtape/$mixtape_album [$first_artist]%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
    tag:mixtape:                 +mixtape/$mixtape_album [$first_artist]%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
#    albumtype:mixtape:           +mixtape/$mixtape_album%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}
#    default:                     %upper{%left{$albumartist,1}}/%title{$first_artist}/%title{$albumartist}%if{$hasyear, │${year}│} %title{$album} [$alb_type$media_type$format]/${padded_tracknr} %title{$title}
    albumtype:soundtrack:        +OST/%if{$hasyear,│${year}│}$album/${padded_tracknr} $artist - %title{$title}
    default:                     %bucket{$albumartist, alpha}/%title{$first_artist}/%title{$albumartist}%if{$hasyear, │${year}│} %title{$album} [$alb_type$media_type$format]/${padded_tracknr} %title{$title}
    comp:                        +VA/%title{$album}%if{$hasyear, (${year})}/${padded_tracknr} $artist - %title{$title}

# https://www.japh.se/2021/05/26/how-to-add-singletons-to-artist-dir-correctly-in-beets.html
    singleton:                   %upper{%left{$artist,1}}/%title{$first_artist_singleton}/+tracks/$base_name

# I want bootlegs etc in the same setup as default
    albumtype:other:             %upper{%left{$albumartist,1}}/%title{$first_artist}/%title{$albumartist}%if{$hasyear, │${year}│} %title{$album} [$alb_type$media_type$format]/${padded_tracknr} %title{$title}
#>
#< inline fun!
item_fields:
# pad track number with zero if < 10
  padded_tracknr: "'{:02n}'.format(track)"
  moh_catalog: catalognum.replace(" ", "")

# capture first artist as primary artist to avoid directories like this:
# · B/Britney Spears/
# · B/Britney Spears feat Madonna/
# · B/Britney Spears vs Metallica/
# > https://github.com/beetbox/beets/issues/3176
# > https://www.japh.se/2021/06/01/capture-primary-artist-as-a-separate-field-in-beets.html
#
# handles:
# · Artist,
# · Artist &
# · Artist feat
# · Artist feat.
# · Artist featuring
# · Artist ft.
# · Artist vs
# · Artist vs.
# · Artist &
#
# The idea is to use $first_artist in the beginning of the path format
# like so:
#
# %title{$first_artist}/%title{$albumartist}
#
# which will put 'Jennifer Lopez feat. Pitbull' inside the main Jennifer
# Lopez directory, but still keep the feat. part in the directory name
# inside it.
#
# J/Jennifer Lopez Feat. Pitbull/Jennifer Lopez Feat. Pitbull │2012│ Dance Again [Single, WEB, MP3]/01 Dance Again.mp3
# -> J/Jennifer Lopez/Jennifer Lopez Feat. Pitbull │2012│ Dance Again [Single, WEB, MP3]/01 Dance Again.mp3


  first_artist: |
    import re
    return re.split(',|\s+(feat(.?|uring)|&|(Vs|Ft).)', albumartist, 1, flags=re.IGNORECASE)[0]

  first_artist_singleton: |
    import re
    return re.split(',|\s+(feat(.?|uring)|&|(Vs|Ft).)', artist, 1, flags=re.IGNORECASE)[0]

# file basename for singletons import - import as is, minus the extension.
  base_name: |
    import os.path
    base = os.path.basename(path)
    return os.path.splitext(base)[0]

album_fields:
  mixtape_album: |
    import re
    album_fixed = album
    return re.sub(r"G.unit Radio,?\s+(Pt|Part)[.]?\s*(.*)", r"G-Unit Radio \2", album_fixed, flags=re.IGNORECASE)

  alb_status: |
    # MB returns 4 values describing how "offical" a release is, they are:
    # Official, Promotional, Bootleg, and Pseudo-Release
    # We only note the middle two.
    # https://musicbrainz.org/doc/Release#Status
    if 'Promo' in albumstatus:
      return 'Promo'
    elif 'Bootleg' in albumstatus:
      return 'Bootleg'
    else:
      return None
  # Check if https://github.com/beetbox/beets/issues/2200 affects below
  alb_type: |
    alb_types = ""
    albumtypes_list = {
      'ep': 'EP, ',
      'single': 'Single, ',
      'live': 'Live, ',
      'remix': 'Remix, ',
      'dj-mix': 'DJ-mix, ',
      'mixtape/street': 'Mixtape, ',
      'interview': 'Interview, ',
    }
    for key, value in albumtypes_list.items():
      if albumtype == key:
        alb_types += str(value)
      if alb_types is not None:
        return alb_types
      else:
        return None

  media_type: |
      # https://musicbrainz.org/doc/Release/Format
      # Lets Merge the variations of the same medium into the main medium name (Opinonated)
      media_list = {
       '12" Vinyl': 'VINYL, ',
       '10" Vinyl': 'VINYL, ',
       '7" Vinyl': 'VINYL, ',
       'Cassette': 'CASSETTE, ',
       'Digital Media': 'WEB, ',
       'CD': 'CD, ',
       'File': 'WEB, ',
      }
      # Lets omit these instead of converging them under a similar label like above (Opinonated)
      media_types_to_omit = ['Enhanced CD', 'CDDA', 'Blu-spec CD', 'SHM-CD', 'HQCD', '']
      if items[0].media in media_list:
        return str(media_list[items[0].media])
      elif items[0].media in media_types_to_omit:
        return None
      else:
        return str(items[0].media)

  hasyear: 1 if year > 0 else 0
#>
#< autotagger
# To control how tolerant the autotagger is of differences, use the
# strong_rec_thresh option, which reflects the distance threshold below
# which beets will make a “strong recommendation” that the metadata
# be used.
#
# default is 0.04
match:
  strong_rec_thresh: 0.10
  medium_rec_thresh: 0.25
  ignored:           missing_tracks unmatched_tracks
  ignored_media:     ['Data CD', 'DVD', 'DVD-Video', 'Blu-ray', 'HD-DVD',
                      'VCD', 'SVCD', 'UMD', 'VHS']
#>
#< ui
ui:
  color: yes
  colors:
    text_success:         green
    text_warning:         yellow
    text_error:           red
    text_highlight:       blue
    text_highlight_minor: lightgray
    action_default:       turquoise
    action:               blue
#>

Issue Analytics

  • State:open
  • Created 2 years ago
  • Comments:5 (4 by maintainers)

github_iconTop GitHub Comments

2reactions
wisp3rwindcommented, Jun 22, 2021

Sounds like a reasonable improvement — I guess beets is generally not very good at gracefully handling errors. In many cases, that’s probably for the better, since an appropriate action is not easy to infer. But simply skipping ahead to the next album in this specific situation should be fine.

0reactions
sampsyocommented, Jun 22, 2021

Yeah. At the risk of overcomplicating things, what you’re describing is sort of a “transactional” file system interface… ideally, we could batch up several copy/move/etc. operations and ask that either they all complete or none complete. Of course, true transactions are pretty much impossible without support from the OS, but maybe we would want a little utility to do sorta-atomic move/copy operations on sets of files using this “check permissions first, then really do the operation” strategy.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Is there a way to abort execution when vars file is missing?
1 Answer 1 ... If you are unhappy with the error message itself, you can prepend it with a task using assert or...
Read more >
MSProject 2019 circular reference error and tasks are missing
I always get a circular reference error when I open my MSproject file. The error refers to a task which disappeared. Also some...
Read more >
Abort entire run at one task failure - Google Groups
It pauses at the end of each 3 and waits. What I am missing is a way to detect if any of those...
Read more >
Usage | Task - Taskfile
Create a file called Taskfile.yml in the root of your project. The cmds attribute should contain the commands of a task. The example...
Read more >
Error Handling In Playbooks - Ansible Documentation
For example, a task could update a configuration file and notify a handler to restart some ... Sometimes it's desirable to abort the...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found