beetbox / beetbox/beets

Beets paths evaluation depends on YAML mapping order, causing issues with home manager

Open
#6,216 0 comments 1 reaction 0 assignees View on GitHub
Dominant language
Python
Stars
15.7k
Forks
2.1k
Avg merge
4d 21h
Merged PRs (30d)
31

Description

### Problem
Beets’ paths matching depends on the order of YAML mapping keys, but YAML mappings are unordered by specification:

> Mapping
> The content of a mapping node is an **unordered** set of key/value node pairs

https://yaml.org/spec/1.2.2/#nodes

This becomes an issue when generating beets configuration using [home manager](https://github.com/nix-community/home-manager/blob/release-25.11/modules/programs/beets.nix). Home manager emits valid YAML but it doesn’t preserve the key order.

As a result, a path query (like st_type:games) can match before a more specific query (like st_type:games st_variant:remix), even if both are present. This causes albums to be imported into the wrong path.

---
A possible fix would be to make `paths` a list:

```
paths: [
{ query: st_type:games st_variant:remix, template: "soundtracks/games/$mediatitle$mediatitle_disambig_safe/remixes/$inline_year - $album%aunique{}$alb_type$media_type/%if{$multidisc,Disc $disc/}$padded_tracknr. $title" },
{ query: st_type:games st_variant:gamerip, template: "soundtracks/games/$mediatitle$mediatitle_disambig_safe/gamerip/$base_name" },
{ query: st_type:games, template: "soundtracks/games/$mediatitle$mediatitle_disambig_safe/$inline_year - $album%aunique{}$alb_type$media_type/%if{$multidisc,Disc $disc/}$padded_tracknr. $title" }
]
```
Or if possible keep paths as it is to avoid such a breaking change, and introduce a new key that allows configuring paths as a list.

### Setup

* OS: NixOS 25.11
* Python version: 3.13.9
* beets version 2.5.1
* Turning off plugins made problem go away (yes/no): no

My configuration (output of `beet config`) is:

```yaml
paths:
default: artists/%bucket{%the{$albumartist},alpha}/%the{$albumartist}$inline_artist_disambig/$inline_year - $album%aunique{}$alb_type$media_type/%if{$multidisc,Disc $disc/}$padded_tracknr. $title
st_type:games: soundtracks/games/$mediatitle$mediatitle_disambig_safe/$inline_year - $album%aunique{}$alb_type$media_type/%if{$multidisc,Disc $disc/}$padded_tracknr. $title
st_type:games st_variant:gamerip: soundtracks/games/$mediatitle$mediatitle_disambig_safe/gamerip/$base_name
st_type:games st_variant:remix: soundtracks/games/$mediatitle$mediatitle_disambig_safe/remixes/$inline_year - $album%aunique{}$alb_type$media_type/%if{$multidisc,Disc $disc/}$padded_tracknr. $title
```

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.