-
Notifications
You must be signed in to change notification settings - Fork 1
Troubleshooting
🏠 Home › Troubleshooting
Find your symptom in the table, jump to the fix. For anything not covered, open the module's log from Logs in the UI or open an issue.
- Symptom finder
- Startup & container
- Login & auth
- Instances & connections
- Modules
- Webhooks
- Database
- Still stuck?
| Symptom | Likely cause | Jump to |
|---|---|---|
| Container won't start | Bad config, port clash, or permissions | Container won't start |
| Docker healthcheck keeps failing | Slow first-launch DB init or networking | Health check keeps failing |
| First-run setup page never appears | Already configured | First-run page doesn't appear |
| Forgot the admin password | — | Reset the admin password |
Login returns 429
|
Rate limiter fired | Login returns 429 |
| Logged out mid-session | JWT expired | JWT expired mid-session |
| Instance test fails | URL, key, or network | Instance test fails |
Plex returns 401
|
Wrong token | Plex returns 401 |
| Healthy probe but module run fails | Probe is connectivity-only | Healthy probe, module fails |
| Dashboard doesn't update live | Reverse-proxy buffering breaks SSE | Dashboard doesn't update live |
| Cancel button doesn't stop a module | Cooperative cancellation | Cancel doesn't stop a module |
poster_renamerr moves nothing |
Dry-run, paths, or no matches | poster_renamerr moves nothing |
poster_cleanarr does nothing |
Wrong mode knob | poster_cleanarr does nothing |
jduparr runs forever |
First-run full hash | jduparr runs forever |
sync_gdrive "invalid path" |
Path-safety guard | sync_gdrive invalid path |
| Thumbnails slow / low-res filter empty | Dimensions not backfilled | Posters slow or filter empty |
Webhooks return 401
|
Missing secret header | Webhooks return 401 |
| Sonarr "Test connection failed" | Sonarr can't reach CHUB | Sonarr test fails |
chub.db is locked |
Concurrent writer | chub.db is locked |
| Database is huge | Old jobs not purged | Database is huge |
Read the logs first:
docker compose logs chubMatch the error:
| Log line | Fix |
|---|---|
Configuration file not found: /config/config.yml |
Make sure the /config bind-mount exists and is writable, then restart — CHUB writes a default config. |
Configuration validation failed |
CHUB names the bad field. Fix it in config.yml or delete the section (missing sections fall back to defaults) and restart. |
Address already in use |
Port 8000 is taken. Stop the other process or change the ports: line in your compose file. |
Permission denied on /config
|
PUID/PGID don't match the bind-mount owner. Run chown -R <puid>:<pgid> <config-dir> on the host. See Installation → permissions. |
Test the endpoint from the host:
curl http://localhost:8000/api/health-
Works, but Docker still reports unhealthy — it's container networking. Check
docker inspect chuband confirm the port binding. -
Times out on first launch — DB init is slow. Raise
start_periodto90sin your compose healthcheck.
Check whether CHUB already has an admin:
curl http://localhost:8000/api/auth/statusIf it returns { "configured": true } and you don't have the credentials, reset the admin password.
This is the canonical password / login recovery procedure. Pick either method, then reload the web UI — the first-run setup form reappears so you can create a fresh admin account.
Option A — reset command (recommended):
docker compose run --rm chub python3 main.py --reset-authThis clears the username, password, and JWT secret. Restart the container afterward.
Option B — edit config: stop CHUB, open config/config.yml, delete the entire auth: block, then start CHUB again.
Gotcha: Both methods log out every active session (the JWT secret rotates). Anyone using a saved token must log in again.
The login rate limiter fired. Wait 5–10 seconds and retry. If it happens during normal use, you're likely calling POST /api/auth/login per request in a script — reuse one token instead (default expiry 24 h; raise auth.token_expiry_hours for automation).
The frontend auto-redirects to login on a 401. For scripts, call POST /api/auth/login again to get a fresh token.
First time connecting Radarr / Sonarr / Lidarr / Plex? See First-Run for the full walkthrough. This section is for when a connection that worked stops working.
From Settings → Instances, click Test on the failing instance:
| Result | Cause & fix |
|---|---|
| Connection refused | Wrong URL/port. http://radarr:7878 only resolves if both containers share a Docker network. |
| Timeout | ARR is down or a firewall is between them. Confirm from inside CHUB: docker compose exec chub curl -sS <url>/api/v3/system/status -H 'X-Api-Key: <key>'. |
401 / 403
|
Wrong API key. Copy it fresh from the ARR's Settings → General → Security. |
| "URL blocked by network safety check" | Your URL resolves to a reserved/metadata range (SSRF guard, not a bug). Use a normal routable IP or hostname. |
The api field for a Plex instance is the X-Plex-Token, not your Plex login. See Finding a Plex token.
The 6-hour health probe checks basic connectivity only, not the specific endpoints a module uses. Open the module's run log — it shows the exact endpoint and status code that failed.
The browser receives server-sent events from /api/modules/events; if that breaks it silently falls back to polling. Common causes behind a reverse proxy:
-
Buffering — Nginx buffers responses by default and breaks SSE. Add
proxy_buffering off;for the/api/modules/eventslocation. - Gzip on the stream — compression breaks event framing. Disable it for that endpoint.
-
Expired auth —
EventSourcecan't refresh tokens, so an expired JWT drops the stream. Reload the page.
Cancellation is cooperative — a module stops when it next checks the cancel flag.
-
Most modules stop on the next iteration (
poster_renamerr,poster_cleanarr,labelarr,jduparr,nohl,unmatched_assets,upgradinatorr,renameinatorr,health_checkarr,nestarr,sync_gdrive). -
border_replacerrruns to completion — it doesn't check the flag yet. -
plex_maintenanceis partial: PhotoTranscoder cleanup stops cleanly, butempty_trash,clean_bundles, andoptimize_dbrun to completion (Plex's API has no interrupt). Restart the container to kill one mid-run.
Check, in order:
-
dry_run: trueis set. -
source_dirsis empty or wrong. -
destination_dirisn't writable byPUID/PGID. - No matching ARR items — set
log_level: debugand re-run to see per-item match attempts. -
action_type: hardlinkwith source and destination on different filesystems (hardlinks can't cross volumes). Usecopy/move/symlink, or move both paths to one volume.
Three independent operations live in this module — check the right knob. See Modules → poster_cleanarr for the full reference.
-
Plex metadata bloat sweep — driven by top-level
mode:report(dry-run),move,remove,restore,clear,nothing. -
Orphan-asset sweep — set
orphan_assets_enabled: trueand populateasset_dirs;orphan_assets_modetakesreport/move/remove. -
Stale-duplicate sweep — set
stale_duplicates_enabled: trueand populateasset_dirs(shared with orphan);stale_duplicates_modetakesreport/move/remove. Also requiresmedia_cacheto be populated (runposter_renamerrfirst).
Gotcha:
reportlists candidates but changes nothing — that's expected. If the log says "Library title set is empty…" or "No canonical folders found…", runposter_renamerronce first to populatemedia_cache. Also confirmplex_pathis the filesystem path to Plex'sMetadata/directory as seen inside the CHUB container, not a URL.
It's hashing the whole library. The first run on a large tree takes hours; later runs are fast because CHUB remembers what it hashed. To stop, use Settings → Jobs → Cancel — it stops at the next file boundary.
The path-safety guard rejects hash_database, sync_location, gdrive_sa_location, and folder IDs that contain null bytes or start with -. Rewrite the value so it does neither.
CHUB generates and caches thumbnails on demand, and needs each poster's dimensions before the low-resolution filter works. First view of a poster is slow; every view after is instant. Click Backfill dimensions on the poster stats page to pre-warm thumbnails and fill in missing sizes.
Inbound webhook setup,
webhook_secret, and retry tuning are documented on the Webhooks page.
general.webhook_secret is set but the caller isn't sending it. Copy the generated URL from Settings → Webhooks — it embeds the secret (?secret=) for you, or send it as the X-Webhook-Secret header.
Almost always Sonarr can't reach CHUB. Verify from inside Sonarr's container:
docker compose exec sonarr curl -I http://chub:8000/api/healthSQLite allows one writer at a time. You may see this briefly during concurrent cancel/queue operations; CHUB retries automatically. If it persists, something else holds a handle — usually a backup script or another container mounting the DB file.
From Settings → Jobs, use the bulk action to purge completed jobs older than 30 days. Health snapshots older than 30 days prune automatically on the next 6-hour tick. To shrink the file on disk after a large purge, run a DB vacuum from Settings → System.
Gotcha: Log files can also fill disk. Lower
general.max_logs(default 9 rotated files per module); old rotations are deleted on the next write.
- Set the misbehaving module to
log_level: debugand reproduce. - Grab the log excerpt (redacted is fine — CHUB scrubs secrets before writing).
-
Open an issue with:
- What you expected vs. what happened
- CHUB version (
GET /api/version, or the Settings page footer) - Container or bare-metal install
- The log excerpt
Next: FAQ · Related: Configuration, Modules