Skip to content

v2.2.1 — what a review and a tool pass found in 2.2.0

Choose a tag to compare

@Dim145 Dim145 released this 21 Sep 22:19
· 20 commits to master since this release

A correction release: a full review of everything since 2.1.1, plus semgrep, bandit,
gitleaks, trivy, hadolint, shellcheck, actionlint and the dependency audits over the
repository. Fifteen defects, all from 2.2.0, all fixed. Upgrading is a pull.

If you run TMDB in a language other than English, upgrade

2.2.0 compared genre names on ASCII letters and digits alone, so a genre written in
Japanese, Cyrillic, Greek or Korean reduced to nothing and was dropped. With
TMDB_LANGUAGE set to one of those, every title in the library lost its genres and
was cached as a permanent failure
, under a message blaming ignore rules you never
wrote. Letters are now whatever the writing system calls them.

Those cached failures are still sitting behind their retry backoff. Clear them, and only
them, then run again:

plex-auto-genres failures --library "<your library>" --retry

If you have manual bindings, upgrade

The migration that widened bindings to one id per source ran as a script, where every
statement commits on its own. An interruption between dropping the old table and
renaming the new one — a container restart is enough — lost every pinned id in
silence
, and a leftover scratch table made the database refuse to open at all. It is
one transaction now, and it cleans up after an interrupted attempt.

A pinned id is no longer overridden by a guess

The rule that a hand-pinned title is only ever asked of the sources that can read its id
was written into the merge path alone. In the default mode, a pinned source that was
rate limited handed the title to the next source, which searched by name and wrote back
exactly the match the binding existed to override. The rule now holds in both modes, and
a pin no configured source can read says so instead of caching the title as dead.

The rest, in the order a title meets them

  • An answer carrying no genres stopped the fallback chain, so a title whose AniList tags
    were all below the agreement threshold failed for "no usable genres" without the
    sources below it ever being asked.
  • A merge that lost a source to a transient error was cached as complete, freezing that
    title on a subset of its sources for good. It is deferred and completed next run.
  • A merged result took its rating from whichever source had one, which could write one
    record's score beside another record's id.
  • The parallel merge discarded answers already in hand when one source failed in an
    unexpected way, and the connection pool was sized for one request per title while a
    merge asks every source at once — enough to time out and stand a healthy source down.
  • The Plex writer still compared tags by case alone, so on a collection library the
    duplicate collections 2.2.0 set out to remove were appended straight back.
  • The bindings page removed every pin on an item when asked to remove one row, and the
    config editor kept a merge mode alive after hiding its control.
  • Two rename rules that differ only in punctuation cancelled each other in silence; that
    is refused now, with both keys named.

Also

TMDB_LANGUAGE joins the settings fingerprint, since it decides the very strings
written to Plex: if yours is not en-US, this release re-tags those libraries once, on
purpose. doctor warns when useKeywords sits behind a source that has no keywords and
will answer first.

From the tools: semgrep found two shell injections in the release workflow, where a ref
name reached a shell through interpolation; those values go through the environment now.
Trivy found six advisories in the image, all against pip, which nothing at runtime
invokes — it is gone from the final stage, with 6.7 MB and a package installer. Bandit,
gitleaks over the tree and the whole history, hadolint, shellcheck, actionlint,
pip-audit and pnpm audit came back clean, and semgrep now reports nothing anywhere in
the repository.