Skip to content

fix(arrs): route multi-instance categories like radarr-abc to the correct ARR type#674

Open
samtheruby wants to merge 1 commit into
javi11:mainfrom
samtheruby:fix/arr-category-type-routing
Open

fix(arrs): route multi-instance categories like radarr-abc to the correct ARR type#674
samtheruby wants to merge 1 commit into
javi11:mainfrom
samtheruby:fix/arr-category-type-routing

Conversation

@samtheruby

@samtheruby samtheruby commented Jun 10, 2026

Copy link
Copy Markdown

Note

This PR was authored with AI (Claude Code). All code reviewed by a human before submission. Tests written and verified locally.

Summary

Fixes the could not determine ARR type for category: <name> post-process notification failure when users run multiple ARR instances with suffixed categories (e.g. radarr-abc, sonarr-4k, sonarr-anime).

Three complementary changes:

  1. Heuristic (internal/config/manager.go: InferARRTypeFromCategory) — switched the fallback rules from exact equality (category == "radarr") to strings.HasPrefix, so any name beginning with radarr / sonarr / lidarr / readarr / whisparr routes correctly. Helper now lives in internal/config so the startup migration below can reuse it without creating an import cycle (internal/arrs already imports internal/config). internal/importer/postprocessor/arr_notifier.go calls the helper via the config package.

  2. Instance manager (internal/arrs/instances/manager.go) — threaded arrType through ensureCategoryExistsInConfig so newly-created SAB categories have the Type field set from the start, and added a backfill that fills Type on a previously-created category whose Type was left empty when an ARR instance is (re-)registered.

  3. Startup migration (internal/config/manager.go: MigrateCategoryTypes) — on every LoadConfig, walk SABnzbd.Categories and fill any empty Type using the heuristic. When something changes, write a .bak next to config.yaml and persist the updated file. Handles every existing install on first run without forcing users to edit yaml or re-add ARR instances. User-set Type values are never overwritten; names that don't match the heuristic are left alone.

The runtime heuristic in arr_notifier.go stays in place as a defence-in-depth fallback for any category whose Type couldn't be resolved at load time.

Why this matters

SABnzbdCategory.Type is honored by arr_notifier.go but is not exposed in the frontend SAB config form (frontend/src/components/config/SABnzbdConfigSection.tsx only edits name / order / priority / dir). Before this PR, the only ways to set Type were editing config.yaml by hand, or hoping your category name was literally radarr / sonarr / contained movie or tv. Multi-instance setups (one Radarr per quality profile, etc.) all hit the failure mode.

The startup migration means existing affected installs are auto-healed the first time they boot a build that includes this PR — no manual yaml editing required, and the .bak lets users revert if they don't like the change.

Test plan

  • go test ./internal/config/InferARRTypeFromCategory (17 cases) + MigrateCategoryTypes (backfill, preserves-user-set, skips-unknown, no-categories). All pass.
  • go test ./internal/importer/postprocessor/ — 26-case table-driven test for the heuristic via the postprocessor shim, covering all suffixed names plus the existing keyword cases. All pass.
  • go test ./internal/arrs/instances/ — 4 cases for ensureCategoryExistsInConfig: new-category-sets-type, backfills-empty-type-on-existing, preserves-user-set-type, empty-name-defaults-to-default-with-type. All pass.
  • go vet ./... — clean.
  • go build ./... — clean.
  • Manual: deploy a build with this PR onto an install whose categories have empty Type. Confirm the INFO Backfilled SABnzbd category types from heuristic categories=[...] count=N log line on first start, config.yaml.bak is written, and post-process notification fires (no could not determine ARR type log).
  • Manual: register a new ARR instance with a suffixed category (e.g. radarr-abc), confirm the SABnzbd category gets type: radarr written from the start.

@samtheruby samtheruby changed the title fix(arrs): route multi-instance categories like radarr-sqp1 to the correct ARR type fix(arrs): route multi-instance categories like radarr-abc to the correct ARR type Jun 10, 2026
…rrect ARR type

Fix the "could not determine ARR type for category: <name>" post-process
notification failure when users run multiple ARR instances with suffixed
categories (e.g. radarr-sqp1, sonarr-4k, sonarr-anime).

Three complementary changes:

1. Heuristic (config.InferARRTypeFromCategory): switched the fallback rules
   from exact equality (category == "radarr") to strings.HasPrefix so any
   name beginning with "radarr"/"sonarr"/"lidarr"/"readarr"/"whisparr" routes
   correctly. Moved the helper from internal/importer/postprocessor into
   internal/config so the startup migration below can reuse it without
   creating an import cycle.

2. Instance manager: threaded arrType through ensureCategoryExistsInConfig
   so newly-created SAB categories have the Type field set from the start.
   Also backfills Type on a previously-created category whose Type was left
   empty.

3. Startup migration (config.MigrateCategoryTypes): on every LoadConfig,
   walk SABnzbd.Categories and fill any empty Type using the heuristic.
   When something changes, write a .bak alongside config.yaml and persist
   the updated file. This handles every existing install on first run
   without forcing users to edit yaml or re-add ARR instances. Existing
   user-set Type values are preserved.

The runtime heuristic in arr_notifier remains as a defence-in-depth fallback
for any category whose Type couldn't be resolved at load time.
@samtheruby samtheruby force-pushed the fix/arr-category-type-routing branch from 1a4f140 to 97fb481 Compare June 10, 2026 06:14
// inferARRTypeFromCategory is a thin shim around config.InferARRTypeFromCategory
// kept so the existing table-driven test in this package continues to compile.
// Prefer calling config.InferARRTypeFromCategory directly from new code.
func inferARRTypeFromCategory(categoryName string) string {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this function used at all?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants