*/30 * * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/critical_sync_maintenance.sh" "/boot/config/plugins/varaverk/Orchestrators/critical_sync_maintenance.sh"
0 1 * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/daily_sync_maintenance.sh" "/boot/config/plugins/varaverk/Orchestrators/daily_sync_maintenance.sh"
0 */4 * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/intermediate_sync_maintenance.sh" "/boot/config/plugins/varaverk/Orchestrators/intermediate_sync_maintenance.sh"
0 0 15 * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/monthly_maintenance.sh" "/boot/config/plugins/varaverk/Orchestrators/monthly_maintenance.sh"
0 7 * * 0 bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/sunday_morning_coffee_report.sh" "/boot/config/plugins/varaverk/Orchestrators/sunday_morning_coffee_report.sh"
*/7 * * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/transcode_management.sh" "/boot/config/plugins/varaverk/Orchestrators/transcode_management.sh"
*/15 * * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/watchdog_orchestrator.sh" "/boot/config/plugins/varaverk/Orchestrators/watchdog_orchestrator.sh"
30 2 * * 0 bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Orchestrators/weekly_sync_maintenance.sh" "/boot/config/plugins/varaverk/Orchestrators/weekly_sync_maintenance.sh"
* * * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Plugin/unraid/Tools/api_cache_writer.sh" "/boot/config/plugins/varaverk/Plugin/unraid/Tools/api_cache_writer.sh"
0 */2 * * * bash "/boot/config/plugins/varaverk/Plugin/unraid/run_job.sh" "Plugin/unraid/Tools/remote_arr_cache_writer.sh" "/boot/config/plugins/varaverk/Plugin/unraid/Tools/remote_arr_cache_writer.sh"


Bash

grep -n "log\|tee\|exec\|output\|watchdog_orchestrator" /boot/config/plugins/varaverk/Plugin/unraid/run_job.sh | head -20

Find logging/output handling in run_job.sh


2:# Varaverk job runner — wraps script execution with JSON status tracking.
12:# Writes: /var/log/varaverk/<id>.json — status, timestamps, exit code, pid
13:#         /var/log/varaverk/<id>.log  — appended per run, trimmed to LOG_MAX_LINES
14:#         /var/log/varaverk/<id>.manual_ts — sentinel: epoch of last manual completion
22:LOG_DIR="/var/log/varaverk"
24:LOG_FILE="$LOG_DIR/$BASE.log"


List varaverk log directory


Orchestrators/
Plugin/
Tools/
git_pull_execute.json
git_pull_execute.log
git_pull_execute.manual_ts
rebuild_cron.log


List orchestrator logs


array_started.json
array_started.log
critical_sync_maintenance.json
critical_sync_maintenance.log
daily_sync_maintenance.json
daily_sync_maintenance.log
intermediate_sync_maintenance.json
intermediate_sync_maintenance.log
sunday_morning_coffee_report.json
sunday_morning_coffee_report.log
transcode_management.json
transcode_management.log
watchdog_orchestrator.json
watchdog_orchestrator.log
weekly_sync_maintenance.json
weekly_sync_maintenance.log


Debug failed Emby and Critical-Data sync jobs


Read current watchdog orchestrator log


━━━ ⚡ Stability Watchdog — 2026-06-07 08:45:31 ━━━
System healthy ✅ (08:45:31)

── 2026-06-07 09:00:01 ────────────────────────────────────────────────

━━━ ⚙ Resource Manager — HOST1 — 09:00:01 ━━━
  RAM: 48GB free   Load: 9.00   Action: 0 → 0 (normal)
━━━ 🐾 Docker Watchdog — 2026-06-07 09:00:01 ━━━
All healthy ✅ — 60 containers (09:00:07)
━━━ 🛡 System Watchdog — 2026-06-07 09:00:07 ━━━
━━━ 💾 Storage Watchdog — 2026-06-07 09:00:08 ━━━
Storage healthy ✅ (09:00:26)
WebGUI responding — healthy ✅
━━━ 🌐 Network Watchdog — 2026-06-07 09:00:26 ━━━
Network healthy ✅ (09:00:26)
API key synced to conf ✅ — HOST1_UNRAID_API_KEY = 1825c3a2...4dbb
━━━ ⚡ Stability Watchdog — 2026-06-07 09:00:29 ━━━
System healthy ✅ (09:00:29)

── 2026-06-07 09:15:01 ────────────────────────────────────────────────

━━━ ⚙ Resource Manager — HOST1 — 09:15:01 ━━━
  RAM: 51GB free   Load: 8.82   Action: 0 → 0 (normal)
━━━ 🐾 Docker Watchdog — 2026-06-07 09:15:01 ━━━
All healthy ✅ — 60 containers (09:15:07)
━━━ 🛡 System Watchdog — 2026-06-07 09:15:07 ━━━
━━━ 💾 Storage Watchdog — 2026-06-07 09:15:08 ━━━
Storage healthy ✅ (09:15:42)
WebGUI responding — healthy ✅
━━━ 🌐 Network Watchdog — 2026-06-07 09:15:43 ━━━
Network healthy ✅ (09:15:43)
API key synced to conf ✅ — HOST1_UNRAID_API_KEY = 1825c3a2...4dbb
━━━ ⚡ Stability Watchdog — 2026-06-07 09:15:45 ━━━
System healthy ✅ (09:15:46)

── 2026-06-07 09:30:01 ────────────────────────────────────────────────

━━━ ⚙ Resource Manager — HOST1 — 09:30:01 ━━━
  RAM: 45GB free   Load: 10.16   Action: 0 → 0 (normal)
━━━ 🐾 Docker Watchdog — 2026-06-07 09:30:01 ━━━
All healthy ✅ — 60 containers (09:30:07)
━━━ 🛡 System Watchdog — 2026-06-07 09:30:07 ━━━
━━━ 💾 Storage Watchdog — 2026-06-07 09:30:07 ━━━
Storage healthy ✅ (09:30:23)
WebGUI responding — healthy ✅
━━━ 🌐 Network Watchdog — 2026-06-07 09:30:23 ━━━
Network healthy ✅ (09:30:23)
API key synced to conf ✅ — HOST1_UNRAID_API_KEY = 1825c3a2...4dbb
━━━ ⚡ Stability Watchdog — 2026-06-07 09:30:26 ━━━
System healthy ✅ (09:30:27)


Watchdog is clean — three consecutive healthy cycles, `emby-test` is gone. The `failed_containers:1` in the system state is just a stale counter. Let me check if the system watchdog will clear it on its own or needs a nudge.


grep -n "failed_containers\|set_strikes\|clear_strikes" /boot/config/plugins/varaverk/Watchdogs/system_watchdog.sh | head -20

Find how failed_containers strike is managed in system_watchdog


(Bash completed with no output)


grep -n "failed_containers" /boot/config/plugins/varaverk/Watchdogs/*.sh /boot/config/plugins/varaverk/Orchestrators/*.sh 2>/dev/null | head -20

Find all references to failed_containers across watchdog scripts


grep -rn "failed_containers" /boot/config/plugins/varaverk/ 2>/dev/null

Find all references to failed_containers in the entire varaverk workspace


grep -n "set_strikes\|SYSTEM_WATCHDOG_STATE\|STATE_FILE\|failed\|containers" /boot/config/plugins/varaverk/Watchdogs/system_watchdog.sh | head -30

Find state file writes in system_watchdog


15:# A failed script is logged but does not prevent remaining scripts from running.
21:#   Non-fatal steps      — a failed step is logged; remaining steps still run
110:            error "$script_name — chmod +x failed"


grep -n "set_strikes\|STATE_FILE\|watchdog_state\|SYSTEM_WATCHDOG" /boot/config/plugins/varaverk/Watchdogs/stability_watchdog.sh 2>/dev/null | head -20; grep -n "set_strikes\|STATE_FILE\|watchdog_state\|failed_containers" /boot/config/plugins/varaverk/Watchdogs/stability_watchdog.sh 2>/dev/null | head -20

Check stability_watchdog for the failed_containers state


86:#   SYS_WATCHDOG_STATE_FILE  — strike counters and cycle state
135:for state_file in "$SYS_WATCHDOG_STATE_FILE" "$SYS_WATCHDOG_REBOOT_LOG" \
200:    grep -E "^${1}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d':' -f2
203:set_strikes() {
205:    grep -vE "^${key}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
206:    echo "${key}:${count}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
207:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
216:    set_strikes "$key" "$current"
220:reset_strikes() {
221:    set_strikes "$1" 0
225:    grep -E "^${1}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d'=' -f2
230:    grep -vE "^${key}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
231:    echo "${key}=${val}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
232:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
346:            reset_strikes "$key"
352:        [[ -n "$current" && "$current" -gt 0 ]] && reset_strikes "$key"
484:    # to WATCHDOG_STATE_FILE. We read that flag and run through the standard strike system.
486:        _daemon_down=$(grep -oP "(?<=^daemon_confirmed_down:)[^:]*" "$WATCHDOG_STATE_FILE" 2>/dev/null || echo "false")
629:            reset_strikes "ram"
732:                    reset_strikes "sshd"
86:#   SYS_WATCHDOG_STATE_FILE  — strike counters and cycle state
135:for state_file in "$SYS_WATCHDOG_STATE_FILE" "$SYS_WATCHDOG_REBOOT_LOG" \
200:    grep -E "^${1}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d':' -f2
203:set_strikes() {
205:    grep -vE "^${key}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
206:    echo "${key}:${count}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
207:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
216:    set_strikes "$key" "$current"
220:reset_strikes() {
221:    set_strikes "$1" 0
225:    grep -E "^${1}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d'=' -f2
230:    grep -vE "^${key}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
231:    echo "${key}=${val}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
232:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
346:            reset_strikes "$key"
352:        [[ -n "$current" && "$current" -gt 0 ]] && reset_strikes "$key"
484:    # to WATCHDOG_STATE_FILE. We read that flag and run through the standard strike system.
486:        _daemon_down=$(grep -oP "(?<=^daemon_confirmed_down:)[^:]*" "$WATCHDOG_STATE_FILE" 2>/dev/null || echo "false")
629:            reset_strikes "ram"
732:                    reset_strikes "sshd"


grep -n "failed_containers\|T2_WARNINGS\|WARNINGS\|docker.*fail\|failed.*docker\|container.*fail" /boot/config/plugins/varaverk/Watchdogs/stability_watchdog.sh | head -20

Find failed_containers reference in stability_watchdog


grep -rn "failed_containers" /boot/config/plugins/varaverk/ --include="*.sh" --include="*.conf" --include="*.php" 2>/dev/null

Exhaustive search for failed_containers across all script types


grep -n "WATCHDOG_STATE_FILE\|docker.*warn\|T2_WARN\|restarts\|warnings\|strike" /boot/config/plugins/varaverk/Watchdogs/stability_watchdog.sh | head -30

Find how stability_watchdog tracks docker watchdog warnings


20:#   Tier 1 — CRITICAL (bypass all strikes, reboot immediately)
25:#     (Docker daemon: owned by docker_watchdog — writes daemon_confirmed_down flag → standard strikes)
27:#   Tier 2 — URGENT (bypass strikes when OOM confirms active crisis)
30:#     Without OOM confirmation → standard strike system applies.
38:#   MEM_GB           (4GB) — strike system → reboot (bypass with OOM confirmation)
86:#   SYS_WATCHDOG_STATE_FILE  — strike counters and cycle state
101:#     Show config, thresholds, current system state, and strike counts.
135:for state_file in "$SYS_WATCHDOG_STATE_FILE" "$SYS_WATCHDOG_REBOOT_LOG" \
145:log "$ICON_GEAR Config: strikes=${SYS_WATCHDOG_STRIKE_LIMIT} reboot-limit=${SYS_WATCHDOG_REBOOT_LIMIT}/${SYS_WATCHDOG_REBOOT_WINDOW_HRS}hr oom-limit=${SYS_WATCHDOG_OOM_LIMIT}"
156:    echo "── Tier 1 — CRITICAL (bypass strikes immediately) ──"
163:    echo "── Tier 2 — URGENT (bypass strikes with OOM confirmation) ──"
167:    echo "── Tier 3 — STANDARD (strike system) ──"
171:    echo "$ICON_MEM    RAM reboot:           < ${SYS_WATCHDOG_MEM_GB}GB (+ strikes)"
199:get_strikes() {
200:    grep -E "^${1}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d':' -f2
203:set_strikes() {
205:    grep -vE "^${key}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
206:    echo "${key}:${count}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
207:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
210:increment_strikes() {
213:    current=$(get_strikes "$key")
216:    set_strikes "$key" "$current"
220:reset_strikes() {
221:    set_strikes "$1" 0
225:    grep -E "^${1}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d'=' -f2
230:    grep -vE "^${key}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
231:    echo "${key}=${val}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
232:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
338:run_strike_check() {
341:        local strikes


grep -n "failed_containers\|docker_watchdog\|WATCHDOG_STATE_FILE\|T2_WARNINGS\|T2_RESTARTS" /boot/config/plugins/varaverk/Watchdogs/stability_watchdog.sh | head -20

Find docker watchdog result parsing in stability_watchdog


10:# single-pass run. Works alongside docker_watchdog.sh which handles
12:# docker_watchdog.sh cannot resolve the condition.
25:#     (Docker daemon: owned by docker_watchdog — writes daemon_confirmed_down flag → standard strikes)
54:#   (Container health is owned by docker_watchdog — not checked here.)
86:#   SYS_WATCHDOG_STATE_FILE  — strike counters and cycle state
135:for state_file in "$SYS_WATCHDOG_STATE_FILE" "$SYS_WATCHDOG_REBOOT_LOG" \
200:    grep -E "^${1}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d':' -f2
205:    grep -vE "^${key}:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
206:    echo "${key}:${count}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
207:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
225:    grep -E "^${1}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | cut -d'=' -f2
230:    grep -vE "^${key}=" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null > "${SYS_WATCHDOG_STATE_FILE}.tmp"
231:    echo "${key}=${val}" >> "${SYS_WATCHDOG_STATE_FILE}.tmp"
232:    mv "${SYS_WATCHDOG_STATE_FILE}.tmp" "$SYS_WATCHDOG_STATE_FILE"
481:    # ── Docker daemon — delegated to docker_watchdog ─────────────────────────────────────────
482:    # docker_watchdog owns daemon restart attempts (strike system + rc.docker restart).
484:    # to WATCHDOG_STATE_FILE. We read that flag and run through the standard strike system.
486:        _daemon_down=$(grep -oP "(?<=^daemon_confirmed_down:)[^:]*" "$WATCHDOG_STATE_FILE" 2>/dev/null || echo "false")
489:        run_strike_check "docker_daemon" "$TRIGGERED" "Docker daemon confirmed down by docker_watchdog" && \
773:    # Container health is owned entirely by docker_watchdog: strike system, restart attempts,


grep -n "failed_containers" /boot/config/plugins/varaverk/Plugin/unraid/Tools/health_digest.sh 2>/dev/null | head -10

Check health_digest.sh for failed_containers reference


grep -rn "failed_containers" /boot/config/plugins/varaverk/ 2>/dev/null; grep -rn "failed_containers" /var/log/varaverk/ 2>/dev/null | head -5

Last-resort search for failed_containers including logs


/var/log/varaverk/Orchestrators/sunday_morning_coffee_report.log:380:  🚨 System strikes: 4 active — failed_containers:1 kernel_oops_count=00 mdstat_errors=0 watchdog_cycle=1780830954


grep -n "system_watchdog_state\|SYS_WATCHDOG_STATE\|strikes\|failed" /boot/config/plugins/varaverk/Plugin/unraid/Tools/health_digest.sh | head -30

Find how health_digest reads system watchdog state


ugrep: warning: /boot/config/plugins/varaverk/Plugin/unraid/Tools/health_digest.sh: No such file or directory


find /boot/config/plugins/varaverk -name "health_digest*" 2>/dev/null

Find health_digest script location


find /boot/config/plugins/varaverk -name "*digest*" 2>/dev/null

Find digest script


grep -n "system_watchdog\|SYS_WATCHDOG\|failed_containers\|strikes\|strike" /boot/config/plugins/varaverk/Monitors/weekly_health_digest.sh | head -20

Find system watchdog state reading in weekly_health_digest


12:# Reads state files from across the system (watchdog strikes, fallback state,
35:#   WATCHDOG_STATE_FILE           — active container watchdog strikes
36:#   SYS_WATCHDOG_STATE_FILE       — active system watchdog strikes
77:#       Send smart profile notification if any active watchdog strikes. (default: true)
205:log "Reading: fallback=$FALLBACK_STATE_FILE skip=$DOCKER_WATCHDOG_FAILED_FILE watchdog=$WATCHDOG_STATE_FILE sys=$SYS_WATCHDOG_STATE_FILE"
235:        DIGEST_LINES+=("$ICON_WATCHDOG Container strikes: $ACTIVE_STRIKES active — $STRIKE_LIST")
236:        FINDINGS+=("Container watchdog: $ACTIVE_STRIKES active strikes")
239:        DIGEST_LINES+=("$ICON_WATCHDOG Container watchdog: no active strikes ✅")
244:if [[ -f "$SYS_WATCHDOG_STATE_FILE" ]]; then
245:    SYS_STRIKES=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")
247:        SYS_STRIKE_LIST=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')
248:        DIGEST_LINES+=("$ICON_REBOOT_SMART System strikes: $SYS_STRIKES active — $SYS_STRIKE_LIST")
249:        FINDINGS+=("System watchdog: $SYS_STRIKES active strikes")
252:        DIGEST_LINES+=("$ICON_REBOOT_SMART System watchdog: no active strikes ✅")


Found the bug. The digest counts all lines not ending in `:0`, but the state file has two formats — `:` for strikes and `=` for state values. `kernel_oops_count=00`, `mdstat_errors=0`, and `watchdog_cycle=1780839027` are being falsely counted as strikes. Only `failed_containers:1` is a real one.

Let me verify the actual "4 strikes" breakdown:


grep -v ":0$" /boot/config/plugins/varaverk/State_Files/system_watchdog_state.db

Show exactly what the digest counted as active strikes


failed_containers:1
kernel_oops_count=00
mdstat_errors=0
watchdog_cycle=1780839027


So the "4 strikes" are really: 1 real strike + 3 false positives from `=` style state entries slipping past the `:0` filter. Two bugs here:

1. **Digest false positive** — `grep -v ":0$"` picks up `=` entries that aren't strikes
2. **`kernel_oops_count=00`** — value is `"00"` not `"0"`, would fool even a fixed filter

Let me also find who wrote `failed_containers:1` since nothing references it.


grep -n "failed\|T2_WARN\|WATCHDOG_STATE\|SYS_WATCHDOG_STATE" /boot/config/plugins/varaverk/Watchdogs/docker_watchdog.sh | grep -v "^[0-9]*:#" | head -20

Find where docker_watchdog writes to the system watchdog state file


264:touch "$WATCHDOG_STATE_FILE" "$WATCHDOG_CONTAINER_RESTART_LOG" \
474:WATCHDOG_DAEMON_STRIKE_LIMIT="${WATCHDOG_DAEMON_STRIKE_LIMIT:-3}"    # consecutive failed checks before restart attempt (master.conf)
477:WATCHDOG_DAEMON_STRIKES=$(get_strikes "daemon_strikes" "$WATCHDOG_STATE_FILE")
479:_dr_raw=$(get_strikes "daemon_restarted_flag" "$WATCHDOG_STATE_FILE")
531:            set_strikes "daemon_strikes" 0 "$WATCHDOG_STATE_FILE"
532:            set_strikes "daemon_restarted_flag" "false" "$WATCHDOG_STATE_FILE"
536:        set_strikes "daemon_confirmed_down" "false" "$WATCHDOG_STATE_FILE"
541:    set_strikes "daemon_strikes" "$WATCHDOG_DAEMON_STRIKES" "$WATCHDOG_STATE_FILE"
553:        set_strikes "daemon_confirmed_down" "true" "$WATCHDOG_STATE_FILE"
554:        queue_notify "Docker daemon hung on $(hostname) — restart failed — stability_watchdog escalating" "critical"
569:    set_strikes "daemon_restarted_flag" "true" "$WATCHDOG_STATE_FILE"
579:            set_strikes "daemon_strikes" 0 "$WATCHDOG_STATE_FILE"
580:            set_strikes "daemon_restarted_flag" "false" "$WATCHDOG_STATE_FILE"
581:            set_strikes "daemon_confirmed_down" "false" "$WATCHDOG_STATE_FILE"
586:            set_strikes "daemon_confirmed_down" "true" "$WATCHDOG_STATE_FILE"
587:            queue_notify "Docker daemon restart failed on $(hostname) — stability_watchdog escalating" "critical"
593:        error "Failed to issue Docker daemon restart — platform_restart_service docker failed"
594:        set_strikes "daemon_confirmed_down" "true" "$WATCHDOG_STATE_FILE"
595:        queue_notify "Docker daemon restart command failed on $(hostname) — stability_watchdog escalating" "critical"
613:    T2_WARNINGS=0


grep -n "SYS_WATCHDOG_STATE\|sys_watchdog_state\|failed_containers\|T2_WARNINGS\|result_key" /boot/config/plugins/varaverk/Watchdogs/docker_watchdog.sh | grep -v "^[0-9]*:#" | tail -30

Find SYS_WATCHDOG_STATE_FILE writes in docker_watchdog


613:    T2_WARNINGS=0
866:                ((T2_WARNINGS++))
889:                    ((T2_WARNINGS++))
917:                    ((T2_WARNINGS++))
947:                ((T2_WARNINGS++))
979:                ((T2_WARNINGS++))
997:    TOTAL_WARNINGS=$(( T1_WARNINGS + T2_WARNINGS ))
1002:        echo "$ICON_WATCHDOG T1: $T1_RESTARTS restarts / $T1_WARNINGS warnings   T2: $T2_RESTARTS restarts / $T2_WARNINGS warnings"


grep -n "SYS_WATCHDOG_STATE\|set_strikes.*SYS\|failed_containers" /boot/config/plugins/varaverk/Watchdogs/docker_watchdog.sh | grep -v "^[0-9]*:#" | head -20

Check if docker_watchdog writes to SYS_WATCHDOG_STATE_FILE


990
991
992	    # ── Send notifications ────────────────────────────────────────────────────────────────────
993	    flush_notify
994
995	    # ── Cycle summary — quiet when healthy ───────────────────────────────────────────────────
996	    TOTAL_RESTARTS=$(( T1_RESTARTS + T2_RESTARTS ))
997	    TOTAL_WARNINGS=$(( T1_WARNINGS + T2_WARNINGS ))
998	    CYCLE_END=$(date +%s)
999
1000	    CONTAINER_COUNT=$(docker ps -q 2>/dev/null | wc -l | tr -d ' ')
1001	    if [[ "$TOTAL_RESTARTS" -gt 0 || "$TOTAL_WARNINGS" -gt 0 ]]; then
1002	        echo "$ICON_WATCHDOG T1: $T1_RESTARTS restarts / $T1_WARNINGS warnings   T2: $T2_RESTARTS restarts / $T2_WARNINGS warnings"
1003	        echo "$ICON_TIME      Duration: $(format_duration $(( CYCLE_END - CYCLE_START )))   Containers: $CONTAINER_COUNT"
1004	        echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
1005	    else
1006	        echo "All healthy ✅ — ${CONTAINER_COUNT} containers ($(date '+%H:%M:%S'))"
1007	    fi

    # ── Send notifications ────────────────────────────────────────────────────────────────────
    flush_notify

    # ── Cycle summary — quiet when healthy ───────────────────────────────────────────────────
    TOTAL_RESTARTS=$(( T1_RESTARTS + T2_RESTARTS ))
    TOTAL_WARNINGS=$(( T1_WARNINGS + T2_WARNINGS ))
    CYCLE_END=$(date +%s)

    CONTAINER_COUNT=$(docker ps -q 2>/dev/null | wc -l | tr -d ' ')
    if [[ "$TOTAL_RESTARTS" -gt 0 || "$TOTAL_WARNINGS" -gt 0 ]]; then
        echo "$ICON_WATCHDOG T1: $T1_RESTARTS restarts / $T1_WARNINGS warnings   T2: $T2_RESTARTS restarts / $T2_WARNINGS warnings"
        echo "$ICON_TIME      Duration: $(format_duration $(( CYCLE_END - CYCLE_START )))   Containers: $CONTAINER_COUNT"
        echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
    else
        echo "All healthy ✅ — ${CONTAINER_COUNT} containers ($(date '+%H:%M:%S'))"
    fi


`failed_containers:1` is an orphan — no current script writes it, so it'll never self-clear. The "4 strikes" are actually just this one real-but-stale entry plus three `=` style state values slipping through the `:0` filter in the digest. Two fixes needed:

1. Clear the orphaned strike from the state file
2. Fix the digest to only count `:` separator lines (actual strikes), not `=` style state values


240	    fi
241	fi
242
243	# ── System Watchdog Strikes ───────────────────────────────────────────────────────────────────
244	if [[ -f "$SYS_WATCHDOG_STATE_FILE" ]]; then
245	    SYS_STRIKES=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")
246	    if [[ "$SYS_STRIKES" -gt 0 ]]; then
247	        SYS_STRIKE_LIST=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')
248	        DIGEST_LINES+=("$ICON_REBOOT_SMART System strikes: $SYS_STRIKES active — $SYS_STRIKE_LIST")
249	        FINDINGS+=("System watchdog: $SYS_STRIKES active strikes")
250	        [[ "$DIGEST_SMART_ON_WATCHDOG" == true ]] && SHOULD_SEND=true
251	    else
252	        DIGEST_LINES+=("$ICON_REBOOT_SMART System watchdog: no active strikes ✅")
253	    fi
254	fi

    fi
fi

# ── System Watchdog Strikes ───────────────────────────────────────────────────────────────────
if [[ -f "$SYS_WATCHDOG_STATE_FILE" ]]; then
    SYS_STRIKES=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")
    if [[ "$SYS_STRIKES" -gt 0 ]]; then
        SYS_STRIKE_LIST=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')
        DIGEST_LINES+=("$ICON_REBOOT_SMART System strikes: $SYS_STRIKES active — $SYS_STRIKE_LIST")
        FINDINGS+=("System watchdog: $SYS_STRIKES active strikes")
        [[ "$DIGEST_SMART_ON_WATCHDOG" == true ]] && SHOULD_SEND=true
    else
        DIGEST_LINES+=("$ICON_REBOOT_SMART System watchdog: no active strikes ✅")
    fi
fi


Edit

    SYS_STRIKES=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")
    if [[ "$SYS_STRIKES" -gt 0 ]]; then
        SYS_STRIKE_LIST=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')

    SYS_STRIKES=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -cv -E "(:0$|:false$)")
    if [[ "$SYS_STRIKES" -gt 0 ]]; then
        SYS_STRIKE_LIST=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -v -E "(:0$|:false$)" | tr '\n' ' ')


The file /boot/config/plugins/varaverk/Monitors/weekly_health_digest.sh has been updated successfully. (file state is current in your context — no need to Read it back)

    SYS_STRIKES=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")
    if [[ "$SYS_STRIKES" -gt 0 ]]; then
        SYS_STRIKE_LIST=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')

    SYS_STRIKES=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -cv -E "(:0$|:false$)")
    if [[ "$SYS_STRIKES" -gt 0 ]]; then
        SYS_STRIKE_LIST=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -v -E "(:0$|:false$)" | tr '\n' ' ')

# ── System Watchdog Strikes ───────────────────────────────────────────────────────────────────

if [[ -f "$SYS_WATCHDOG_STATE_FILE" ]]; then

-    SYS_STRIKES=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -c ".")

+    SYS_STRIKES=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -cv -E "(:0$|:false$)")

-        SYS_STRIKE_LIST=$(grep -v ":0$" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | tr '\n' ' ')

+        SYS_STRIKE_LIST=$(grep "^[^=]*:" "$SYS_WATCHDOG_STATE_FILE" 2>/dev/null | grep -v -E "(:0$|:false$)" | tr '\n' ' ')

DIGEST_LINES+=("$ICON_REBOOT_SMART System strikes: $SYS_STRIKES active — $SYS_STRIKE_LIST")

FINDINGS+=("System watchdog: $SYS_STRIKES active strikes")

[[ "$DIGEST_SMART_ON_WATCHDOG" == true ]] && SHOULD_SEND=true


Now clear the orphaned `failed_containers` strike:


Bash

sed -i '/^failed_containers:/d' /boot/config/plugins/varaverk/State_Files/system_watchdog_state.db && cat /boot/config/plugins/varaverk/State_Files/system_watchdog_state.db

Remove orphaned failed_containers strike and verify state file


kernel_oops_count=00
ram:0
mdstat_errors=0
sshd:0
watchdog_cycle=1780839027


Good. Now the digest will count 0 strikes — all remaining entries are either `:0` (excluded by filter) or `=` style state values (now excluded by `^[^=]*:` pattern).

Quick check that `kernel_oops_count=00` also behaves correctly with the new filter:


grep "^[^=]*:" /boot/config/plugins/varaverk/State_Files/system_watchdog_state.db | grep -v -E "(:0$|:false$)"

Verify new filter produces zero active strikes


(Bash completed with no output)


Zero active strikes. Let me commit both fixes together.


cd /boot/config/plugins/varaverk && git add Monitors/weekly_health_digest.sh && git commit -m "Fix digest falsely counting = style state entries as system watchdog strikes

grep -v ':0$' was picking up kernel_oops_count=00, mdstat_errors=0, and
watchdog_cycle as active strikes. Restrict to : separator lines only."

Commit the digest filter fix


[main 1e54752] Fix digest falsely counting = style state entries as system watchdog strikes
 1 file changed, 2 insertions(+), 2 deletions(-)
Shell cwd was reset to /root


**Summary of everything from this report:**

| Issue | Status |
|-------|--------|
| Weekly Emby + Critical-Data sync failed | Caused by stuck rsync tee deadlock — **fixed**, will run next week |
| `emby-test` container strikes | Container removed, watchdog clean for 3+ cycles — **resolved** |
| "4 system strikes" | 1 orphaned entry + 3 false positives from digest filter bug — **both cleared** |
| `cert_monitor.sh` failed | `Gmer4Lfe.us` unreachable because HOST2 is still rebuilding — **expected, not urgent** |
| 41 missing files on HOST2 | Files added since `DAILY_RSYNC_ENABLED=false` — **expected, will sync when ready** |
| `kids_tv_shows` 47h avg sync | Same tee deadlock bug, different profile — **fixed by same commit** |


━━━ 🧹 Media Cleaner — anime — HOST1 ━━━

━━━ 🧹 Anime_Movies ━━━

━━━ 🧹 Anime_Movies-Old ━━━

━━━ 🧹 Anime_Shows ━━━

━━━ 🧹 Anime_Shows-Old ━━━

━━━━━ 📋 MEDIA CLEANER SUMMARY ━━━━━
🖥    Identity: HOST1 (unRAID-Gmer4Lfe)
⚙    Profile:  anime
⏱    Duration: 14s
🏁 Status: clean — nothing to remove
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

━━━ 🧹 Media Cleaner — media — HOST1 ━━━

━━━ 🧹 Kids_Movies ━━━

━━━ 🧹 Kids_Tv_Shows ━━━

━━━ 🧹 Movies ━━━

━━━ 🧹 Music ━━━
⚠  [WARN]  Music not found — skipping

━━━ 🧹 Sports ━━━

━━━ 🧹 stand-up_comedy ━━━

━━━ 🧹 Tv_Shows ━━━

━━━━━ 📋 MEDIA CLEANER SUMMARY ━━━━━
🖥    Identity: HOST1 (unRAID-Gmer4Lfe)
⚙    Profile:  media
⏱    Duration: 1m44s
⚠  [WARN]  Skipped:  Music (folders not found)
🏁 Status: clean — nothing to remove
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  HOST1 (unRAID-Gmer4Lfe) — http://localhost:7878

━━━ 🛡 Safety Checks ━━━
ℹ  [INFO]  Radarr has no health check — proceeding
ℹ  [INFO]  Safety layer 1 passed — container healthy

━━━ 🔄 Pre-flight: Radarr Import Scan ━━━
ℹ  [INFO]  Scan targets (5): /mnt/user/Movies /mnt/user/Kids_Movies /mnt/user/Anime_Movies-Old /ext-ufc-ppv /mnt/user/stand-up_comedy/specials
ℹ  [INFO]  Triggering DownloadedMoviesScan (all root folders)
ℹ  [INFO]  Import scan queued (command ID: 4360622) — waiting for completion...
⚠  [WARN]  Import scan reported failed — proceeding anyway

━━━ 🔄 Fetching Radarr Tracked Files ━━━
🏁  [OK]    Radarr version: 6.1.1.10360 (major 6 — tested ✅)
ℹ  [INFO]  Querying Radarr API...
ℹ  [INFO]  Found 2863 movies — fetching movie files...
ℹ  [INFO]  Built in-memory lookup map: 2725 tracked paths
ℹ  [INFO]  2863 movies | 2725 tracked movie files

━━━ 🧹 Scanning Movies Root ━━━
ℹ  [INFO]  Root: /mnt/user/Movies | Orphan age: 7 days
ℹ  [INFO]  Cleaning up empty folders...
ℹ  [INFO]  Empty folders removed

━━━━━ 📋 RADARR CLEANUP SUMMARY ━━━━━
🖥    Identity:        HOST1 (unRAID-Gmer4Lfe)
🔄    Tracked:         2725 files (2863 movies)
🛡  Protected:       28063 files (artwork, subtitles, metadata)
🗑   Orphans:         0 files (0B)
🗑   Junk:            0 files (0B)
⏭    Recent skipped:  0 files (under 7 days)
⏱    Duration:        12m48s

🏁 Clean — nothing to remove
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

ℹ  [INFO]  HOST1 (unRAID-Gmer4Lfe) — tools OK

━━━ 🌐 Lidarr API ━━━
ℹ  [INFO]  Lidarr reachable — http://localhost:8686

━━━ 🔄 Building Album Directory Map ━━━
ℹ  [INFO]  Fetching track files for 1347 artists...
ℹ  [INFO]  Mapped 9486 albums with local tracks

━━━ 🎬 Albums ━━━
ℹ  [INFO]  Processing 11311 albums...
⚠  [WARN]  Failed to fetch: cover.jpg
ℹ  [INFO]  Checked: 9486 | Complete: 0 | Needed art: 9486 | Fetched: 118 | Failed: 9486

━━━ 🎬 Artists ━━━
ℹ  [INFO]  Processing 1347 artists...
⚠  [WARN]  Failed to fetch: folder.jpg
ℹ  [INFO]  Checked: 1347 | Complete: 0 | Needed art: 1347 | Fetched: 0 | Failed: 1330

━━━━━ 📋 LIDARR MISSING ART SUMMARY ━━━━━
🖥    Identity:  HOST1 (unRAID-Gmer4Lfe)
⏱    Duration:  2h 39m
🎬   Albums:    9486 checked | 0 complete | 118 fetched | 9486 failed
🎬   Artists:   1347 checked | 0 complete | 0 fetched | 1330 failed
🏁    Status:    ✅ ALL DONE
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  HOST1 (unRAID-Gmer4Lfe) — http://localhost:7878
  Files: records only (use --delete-files to also remove from disk)

━━━ 🔄 Querying Radarr ━━━
  2868 movies total — 0 dropped from TMDb

━━━━━ 📋 RADARR TMDB REMOVED SUMMARY ━━━━━
🖥   Identity: HOST1 (unRAID-Gmer4Lfe)
🏁   Status:   nothing to remove
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

  HOST1 (unRAID-Gmer4Lfe) — http://localhost:8989
  Files: records only (use --delete-files to also remove from disk)

━━━ 🔄 Querying Sonarr ━━━
  1162 series total — 0 dropped from TVDB

━━━━━ 📋 SONARR TVDB REMOVED SUMMARY ━━━━━
🖥   Identity: HOST1 (unRAID-Gmer4Lfe)
🏁   Status:   nothing to remove
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

━━━ 📦 Docker Update — 2026-06-07 05:28:37 ━━━

⚠  [WARN]  Slskd — not found, skipping
━━━━━ 📋 DOCKER UPDATE SUMMARY ━━━━━
🖥       Identity:    HOST1 (unRAID-Gmer4Lfe)
⏱       Duration:    2m4s
🔄       Pruned:      Total reclaimed space: 0B
🏁 Status: done ✅ — 0 updated, 8 current
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

━━━ 📦 Daily Restart — 2026-06-07 05:30:41 ━━━
🖥 HOST1 (unRAID-Gmer4Lfe) — 9 container(s)
Authelia
  Waiting 5s — Authelia-Secondary depends on Authelia...
Authelia-Secondary
NginxProxyManager
Lldap-Gmer4Lfe
Dispatcharr-Iptv-Users
Dispatcharr
Dispatcharr-Basic
ErsatzTV-Emby
⚠  [WARN]  Slskd does not exist — skipping

━━━ 🔄 Pruning Dangling Images — 2026-06-07 05:31:48 ━━━
━━━━━ 📋 DAILY RESTART SUMMARY ━━━━━
🖥     Identity:  HOST1 (unRAID-Gmer4Lfe)
⏱     Duration:  1m7s
📦 Scope:   8 restarted, 0 skipped, 0 failed
🔄     Pruned:    Total reclaimed space: 0B
🏁     Status:    ALL DONE ✅
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

━━━━━ 📋 DAILY MAINTENANCE SUMMARY ━━━━━
🖥   Identity: HOST1 (unRAID-Gmer4Lfe)
⏱   Window:   2026-06-07 01:00:06 → 05:31:48
⏱   Duration: 4h 31m

🔄  Shares (14):
  ❌ Books — 0s
  ❌ Intros — 0s
  ❌ Kids_Movies — 0s
  ❌ Kids_Tv_Shows — 0s
  ❌ Movies — 0s
  ❌ Music — 0s
  ❌ Music_Videos — 0s
  ❌ Nextcloud — 0s
  ❌ stand-up_comedy — 0s
  ❌ Sports — 0s
  ❌ Anime_Shows-Old — 0s
  ❌ Anime_Movies-Old — 0s
  ❌ Anime_Movies — 0s
  ❌ Anime_Shows — 1s
  Passed: 0/14  Failed: 14/14

⚙  Jobs:
  🏁  git_pull_execute.sh
  🏁  arr_sync.sh
  🏁  media_shares_permissions.sh
  🏁  media_cleaner.sh anime
  🏁  media_cleaner.sh media
  🏁  radarr_cleanup.sh
  🏁  lidarr_missing_art.sh
  🏁  radarr_tmdb_removed.sh
  🏁  sonarr_tvdb_removed.sh
  🏁  docker_update.sh
  🏁  docker_daily_restart.sh

⚠  [WARN]  Status: 14 failure(s)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━


All 14 rsync failures are expected — `DAILY_RSYNC_ENABLED=false`, they exit in 0s without trying. Two things actually worth looking at:

**1. `Slskd` missing** — shows up as a warn in both docker_update and daily_restart. Container doesn't exist but it's still in the config lists. Is it gone permanently or just temporarily down?

**2. Lidarr art** — 9486 albums checked, 0 complete, 9486 failed after 2h39m. That failure count is suspicious. Let me look at what the actual error is.


grep -n "DAILY_RESTART_CONTAINERS\|DOCKER_UPDATE_TARGETS\|slskd\|Slskd" /boot/config/plugins/varaverk/Configurations/host1.conf | head -20

Find Slskd in host1.conf config lists


56:#   DOWNLOADERS             slskd, SABnzbd, qBittorrent credentials and URLs
268:    HOST1_DAILY_RESTART_CONTAINERS=(
277:        "Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index
571:# slskd — clears stuck searches, dead transfers, purges expired failed imports.
575:    HOST1_SLSKD_FAILED_IMPORTS_DIR="/mnt/user/Temp_Storage/Slskd/completed/failed_imports"
753:        "Soularr"                       # Slskd automation — background only


tail -80 /var/log/varaverk/Orchestrators/daily_sync_maintenance.log | grep -A5 "lidarr\|cover\|folder\|Failed to fetch" | head -40

Check lidarr art failure details in daily log


  🏁  lidarr_missing_art.sh
  🏁  radarr_tmdb_removed.sh
  🏁  sonarr_tvdb_removed.sh
  🏁  docker_update.sh
  🏁  docker_daily_restart.sh


━━━ 🧹 Media Cleaner — anime — HOST1 ━━━  ━━━ 🧹 Anime_Movies ━━━  ━━━ 🧹 Anime_Movies-Old ━━━  ━━━ 🧹 Anime_Shows ━━━  ━━━ 🧹 Anime_Shows-Old ━━━  ━━━━━ 📋 MEDIA CLEANER SUMMARY ━━━━━ 🖥    Identity…


find /var/log/varaverk -name "*lidarr*" 2>/dev/null; grep -rn "lidarr_missing_art" /var/log/varaverk/ 2>/dev/null | head -5

Find lidarr missing art log


/var/log/varaverk/Orchestrators/daily_sync_maintenance.log:289:  🏁  lidarr_missing_art.sh
/var/log/varaverk/Orchestrators/daily_sync_maintenance.log:668:  🏁  lidarr_missing_art.sh


find /var/log/varaverk -type f | head -30; find /tmp -name "*lidarr*" 2>/dev/null

Find lidarr art log file location


/var/log/varaverk/git_pull_execute.manual_ts
/var/log/varaverk/git_pull_execute.json
/var/log/varaverk/git_pull_execute.log
/var/log/varaverk/rebuild_cron.log
/var/log/varaverk/Tools/api_cache_writer.log
/var/log/varaverk/Tools/api_cache_writer.json
/var/log/varaverk/Tools/remote_arr_cache_writer.log
/var/log/varaverk/Tools/remote_arr_cache_writer.json
/var/log/varaverk/Orchestrators/transcode_management.log
/var/log/varaverk/Orchestrators/critical_sync_maintenance.log
/var/log/varaverk/Orchestrators/watchdog_orchestrator.log
/var/log/varaverk/Orchestrators/sunday_morning_coffee_report.log
/var/log/varaverk/Orchestrators/sunday_morning_coffee_report.json
/var/log/varaverk/Orchestrators/weekly_sync_maintenance.log
/var/log/varaverk/Orchestrators/weekly_sync_maintenance.json
/var/log/varaverk/Orchestrators/daily_sync_maintenance.log
/var/log/varaverk/Orchestrators/daily_sync_maintenance.json
/var/log/varaverk/Orchestrators/intermediate_sync_maintenance.log
/var/log/varaverk/Orchestrators/critical_sync_maintenance.json
/var/log/varaverk/Orchestrators/intermediate_sync_maintenance.json
/var/log/varaverk/Orchestrators/watchdog_orchestrator.json
/var/log/varaverk/Orchestrators/transcode_management.json
/var/log/varaverk/Orchestrators/array_started.log
/var/log/varaverk/Orchestrators/array_started.json
/var/log/varaverk/Plugin/unraid/Tools/api_cache_writer.log
/var/log/varaverk/Plugin/unraid/Tools/remote_arr_cache_writer.log
/var/log/varaverk/Plugin/unraid/Tools/remote_arr_cache_writer.json
/var/log/varaverk/Plugin/unraid/Tools/api_cache_writer.json
/var/log/varaverk/Plugin/unraid/tools/api_cache_writer.log
/var/log/varaverk/Plugin/unraid/tools/api_cache_writer.json
/tmp/lidarr_dryrun2.txt
/tmp/lidarr_dryrun.txt


grep -n "cover\|folder\|Failed to fetch\|curl\|HTTP\|error\|Error\|fetch" /var/log/varaverk/Orchestrators/daily_sync_maintenance.log | grep -i "lidarr\|art\|cover\|folder\|fetch" | head -20

Find specific lidarr art failure messages in daily log


152:⚠  [WARN]  Skipped:  Music (folders not found)
170:ℹ  [INFO]  Found 2861 movies — fetching movie files...
176:ℹ  [INFO]  Cleaning up empty folders...
177:ℹ  [INFO]  Empty folders removed
202:⚠  [WARN]  Failed to fetch: cover.jpg
207:⚠  [WARN]  Failed to fetch: folder.jpg
213:🎬   Albums:    9316 checked | 0 complete | 4 fetched | 9316 failed
214:🎬   Artists:   1345 checked | 0 complete | 0 fetched | 1330 failed
516:⚠  [WARN]  Skipped:  Music (folders not found)
528:ℹ  [INFO]  Triggering DownloadedMoviesScan (all root folders)
535:ℹ  [INFO]  Found 2863 movies — fetching movie files...
541:ℹ  [INFO]  Cleaning up empty folders...
542:ℹ  [INFO]  Empty folders removed
567:⚠  [WARN]  Failed to fetch: cover.jpg
572:⚠  [WARN]  Failed to fetch: folder.jpg
578:🎬   Albums:    9486 checked | 0 complete | 118 fetched | 9486 failed
579:🎬   Artists:   1347 checked | 0 complete | 0 fetched | 1330 failed


195
196	━━━ 🔄 Building Album Directory Map ━━━
197	ℹ  [INFO]  Fetching track files for 1345 artists...
198	ℹ  [INFO]  Mapped 9316 albums with local tracks
199
200	━━━ 🎬 Albums ━━━
201	ℹ  [INFO]  Processing 9442 albums...
202	⚠  [WARN]  Failed to fetch: cover.jpg
203	ℹ  [INFO]  Checked: 9316 | Complete: 0 | Needed art: 9316 | Fetched: 4 | Failed: 9316
204
205	━━━ 🎬 Artists ━━━
206	ℹ  [INFO]  Processing 1345 artists...
207	⚠  [WARN]  Failed to fetch: folder.jpg
208	ℹ  [INFO]  Checked: 1345 | Complete: 0 | Needed art: 1345 | Fetched: 0 | Failed: 1330
209
210	━━━━━ 📋 LIDARR MISSING ART SUMMARY ━━━━━
211	🖥    Identity:  HOST1 (unRAID-Gmer4Lfe)
212	⏱    Duration:  2h 31m
213	🎬   Albums:    9316 checked | 0 complete | 4 fetched | 9316 failed
214	🎬   Artists:   1345 checked | 0 complete | 0 fetched | 1330 failed

━━━ 🔄 Building Album Directory Map ━━━
ℹ  [INFO]  Fetching track files for 1345 artists...
ℹ  [INFO]  Mapped 9316 albums with local tracks

━━━ 🎬 Albums ━━━
ℹ  [INFO]  Processing 9442 albums...
⚠  [WARN]  Failed to fetch: cover.jpg
ℹ  [INFO]  Checked: 9316 | Complete: 0 | Needed art: 9316 | Fetched: 4 | Failed: 9316

━━━ 🎬 Artists ━━━
ℹ  [INFO]  Processing 1345 artists...
⚠  [WARN]  Failed to fetch: folder.jpg
ℹ  [INFO]  Checked: 1345 | Complete: 0 | Needed art: 1345 | Fetched: 0 | Failed: 1330

━━━━━ 📋 LIDARR MISSING ART SUMMARY ━━━━━
🖥    Identity:  HOST1 (unRAID-Gmer4Lfe)
⏱    Duration:  2h 31m
🎬   Albums:    9316 checked | 0 complete | 4 fetched | 9316 failed
🎬   Artists:   1345 checked | 0 complete | 0 fetched | 1330 failed


The "Fetched" vs "Failed" numbers are suspicious — fetched 4 then 118, but "failed" equals the total checked. Let me look at what "failed" actually means in the script.


find /boot/config/plugins/varaverk -name "lidarr_missing_art*" 2>/dev/null

Find lidarr missing art script


grep -n "Failed\|failed\|complete\|COMPLETE\|fetched\|FETCHED\|needed\|NEEDED\|missing" /boot/config/plugins/varaverk/Media/lidarr_missing_art.sh | head -30

Find counter logic in lidarr_missing_art.sh


8:# Fetch missing album and artist artwork for the Lidarr music library. Downloads
24:# tags or renames media files. Only writes missing artwork files to existing
32:#   curl + jq check        — fail fast if tools missing
63:#   lidarr_missing_art.sh              — fetch all missing artwork
64:#   lidarr_missing_art.sh --dry-run    — preview without downloading
65:#   lidarr_missing_art.sh --log        — verbose per-item output
66:#   lidarr_missing_art.sh --status     — show config and exit
188:    warn "Failed to fetch: $(basename "$dest")"
216:    notify "lidarr_missing_art failed — Lidarr API unreachable on $(hostname)" "Lidarr Missing Art" "warning"
224:ALBUMS_COMPLETE=0
227:ARTISTS_COMPLETE=0
263:    notify "lidarr_missing_art failed — album API empty on $(hostname)" "Lidarr Missing Art" "warning"
283:        (( ALBUMS_COMPLETE++ ))
284:        log "  complete — skipping"
333:ALBUM_FETCHED=$(wc -l < "$LIDARR_TMP/album_fetches" 2>/dev/null || echo 0)
335:ALBUM_MISSING=$(( ALBUMS_CHECKED - ALBUMS_COMPLETE ))
336:info "Checked: $ALBUMS_CHECKED | Complete: $ALBUMS_COMPLETE | Needed art: $ALBUM_MISSING | Fetched: $ALBUM_FETCHED | Failed: $ALBUM_FAILED"
348:    notify "lidarr_missing_art failed — artist API empty on $(hostname)" "Lidarr Missing Art" "warning"
368:        (( ARTISTS_COMPLETE++ ))
369:        log "  complete — skipping"
428:ARTIST_FETCHED=$(wc -l < "$LIDARR_TMP/artist_fetches" 2>/dev/null || echo 0)
430:ARTIST_MISSING=$(( ARTISTS_CHECKED - ARTISTS_COMPLETE ))
431:info "Checked: $ARTISTS_CHECKED | Complete: $ARTISTS_COMPLETE | Needed art: $ARTIST_MISSING | Fetched: $ARTIST_FETCHED | Failed: $ARTIST_FAILED"
442:echo "$ICON_EMBY   Albums:    $ALBUMS_CHECKED checked | $ALBUMS_COMPLETE complete | $ALBUM_FETCHED fetched | $ALBUM_FAILED failed"
443:echo "$ICON_EMBY   Artists:   $ARTISTS_CHECKED checked | $ARTISTS_COMPLETE complete | $ARTIST_FETCHED fetched | $ARTIST_FAILED failed"
449:    notify "Lidarr art fetch complete on $(hostname) — ${ALBUMS_CHECKED} albums, ${ARTISTS_CHECKED} artists processed" "Lidarr Missing Art" "normal"


270	while IFS=$'\t' read -r mbid artist_name album_name album_id; do
271	    raw_dir="${ALBUM_DIR_MAP[$album_id]:-}"
272	    [[ -z "$raw_dir" ]] && continue  # not downloaded, skip
273	    local_path=$(translate_path "$raw_dir")
274	    (( ALBUMS_CHECKED++ ))
275
276	    [[ ! -d "$local_path" ]] && continue
277
278	    log "[$ALBUMS_CHECKED/$total_albums] $artist_name — $album_name"
279
280	    if [[ -f "$local_path/cover.jpg" &&
281	          -f "$local_path/cdart.png"  &&
282	          -f "$local_path/back.jpg"   ]]; then
283	        (( ALBUMS_COMPLETE++ ))
284	        log "  complete — skipping"
285	        continue
286	    fi
287
288	    wait_for_slot
289
290	    (
291	        _fetches=0 _fails=0
292
293	        JSON=""
294	        if [[ -n "$mbid" && "$mbid" != "null" ]]; then
295	            JSON=$(curl_json "http://webservice.fanart.tv/v3/music/albums/$mbid?api_key=$FANART_API_KEY")
296	            sleep "$LIDARR_ART_SLEEP_BETWEEN"
297	        fi
298
299	        if [[ ! -f "$local_path/cover.jpg" ]]; then
300	            IMG=$(echo "$JSON" | jq -r '.[].albumcover[0].url // empty' 2>/dev/null)
301	            if download_if_valid "$IMG" "$local_path/cover.jpg"; then
302	                (( _fetches++ ))
303	            else
304	                query=$(printf "%s %s" "$artist_name" "$album_name" | sed 's/ /+/g')
305	                itunes=$(curl_json "https://itunes.apple.com/search?term=$query&entity=album&limit=1" |
306	                    jq -r '.results[0].artworkUrl100 // empty' 2>/dev/null | sed 's/100x100/600x600/')
307	                if download_if_valid "$itunes" "$local_path/cover.jpg"; then
308	                    (( _fetches++ ))
309	                else
310	                    (( _fails++ ))
311	                fi
312	            fi
313	        fi
314
315	        if [[ ! -f "$local_path/cdart.png" ]]; then
316	            IMG=$(echo "$JSON" | jq -r '.[].cdart[0].url // empty' 2>/dev/null)
317	            if download_if_valid "$IMG" "$local_path/cdart.png"; then (( _fetches++ )); else (( _fails++ )); fi
318	        fi
319
320	        if [[ ! -f "$local_path/back.jpg" ]]; then
321	            IMG=$(echo "$JSON" | jq -r '.[].albumback[0].url // empty' 2>/dev/null)
322	            if download_if_valid "$IMG" "$local_path/back.jpg"; then (( _fetches++ )); else (( _fails++ )); fi
323	        fi
324
325	        (( _fetches > 0 )) && printf '1\n' >> "$LIDARR_TMP/album_fetches"
326	        (( _fails > 0 ))   && printf '1\n' >> "$LIDARR_TMP/album_fails"
327	    ) &
328
329	done < <(echo "$albums" | jq -r '.[] | [(.foreignAlbumId // ""), (.artist.artistName // ""), (.title // ""), (.id | tostring)] | @tsv')
330
331	wait
332
333	ALBUM_FETCHED=$(wc -l < "$LIDARR_TMP/album_fetches" 2>/dev/null || echo 0)
334	ALBUM_FAILED=$(wc -l  < "$LIDARR_TMP/album_fails"   2>/dev/null || echo 0)
335	ALBUM_MISSING=$(( ALBUMS_CHECKED - ALBUMS_COMPLETE ))
336	info "Checked: $ALBUMS_CHECKED | Complete: $ALBUMS_COMPLETE | Needed art: $ALBUM_MISSING | Fetched: $ALBUM_FETCHED | Failed: $ALBUM_FAILED"
337
338	# ==============================================================================================
339	# ━━━ Artists ━━━

while IFS=$'\t' read -r mbid artist_name album_name album_id; do
    raw_dir="${ALBUM_DIR_MAP[$album_id]:-}"
    [[ -z "$raw_dir" ]] && continue  # not downloaded, skip
    local_path=$(translate_path "$raw_dir")
    (( ALBUMS_CHECKED++ ))

    [[ ! -d "$local_path" ]] && continue

    log "[$ALBUMS_CHECKED/$total_albums] $artist_name — $album_name"

    if [[ -f "$local_path/cover.jpg" &&
          -f "$local_path/cdart.png"  &&
          -f "$local_path/back.jpg"   ]]; then
        (( ALBUMS_COMPLETE++ ))
        log "  complete — skipping"
        continue
    fi

    wait_for_slot

    (
        _fetches=0 _fails=0

        JSON=""
        if [[ -n "$mbid" && "$mbid" != "null" ]]; then
            JSON=$(curl_json "http://webservice.fanart.tv/v3/music/albums/$mbid?api_key=$FANART_API_KEY")
            sleep "$LIDARR_ART_SLEEP_BETWEEN"
        fi

        if [[ ! -f "$local_path/cover.jpg" ]]; then
            IMG=$(echo "$JSON" | jq -r '.[].albumcover[0].url // empty' 2>/dev/null)
            if download_if_valid "$IMG" "$local_path/cover.jpg"; then
                (( _fetches++ ))
            else
                query=$(printf "%s %s" "$artist_name" "$album_name" | sed 's/ /+/g')
                itunes=$(curl_json "https://itunes.apple.com/search?term=$query&entity=album&limit=1" |
                    jq -r '.results[0].artworkUrl100 // empty' 2>/dev/null | sed 's/100x100/600x600/')
                if download_if_valid "$itunes" "$local_path/cover.jpg"; then
                    (( _fetches++ ))
                else
                    (( _fails++ ))
                fi
            fi
        fi

        if [[ ! -f "$local_path/cdart.png" ]]; then
            IMG=$(echo "$JSON" | jq -r '.[].cdart[0].url // empty' 2>/dev/null)
            if download_if_valid "$IMG" "$local_path/cdart.png"; then (( _fetches++ )); else (( _fails++ )); fi
        fi

        if [[ ! -f "$local_path/back.jpg" ]]; then
            IMG=$(echo "$JSON" | jq -r '.[].albumback[0].url // empty' 2>/dev/null)
            if download_if_valid "$IMG" "$local_path/back.jpg"; then (( _fetches++ )); else (( _fails++ )); fi
        fi

        (( _fetches > 0 )) && printf '1\n' >> "$LIDARR_TMP/album_fetches"
        (( _fails > 0 ))   && printf '1\n' >> "$LIDARR_TMP/album_fails"
    ) &

done < <(echo "$albums" | jq -r '.[] | [(.foreignAlbumId // ""), (.artist.artistName // ""), (.title // ""), (.id | tostring)] | @tsv')

wait

ALBUM_FETCHED=$(wc -l < "$LIDARR_TMP/album_fetches" 2>/dev/null || echo 0)
ALBUM_FAILED=$(wc -l  < "$LIDARR_TMP/album_fails"   2>/dev/null || echo 0)
ALBUM_MISSING=$(( ALBUMS_CHECKED - ALBUMS_COMPLETE ))
info "Checked: $ALBUMS_CHECKED | Complete: $ALBUMS_COMPLETE | Needed art: $ALBUM_MISSING | Fetched: $ALBUM_FETCHED | Failed: $ALBUM_FAILED"

# ==============================================================================================
# ━━━ Artists ━━━


The Lidarr numbers are misleading but not broken. "Complete" requires all three of `cover.jpg` + `cdart.png` + `back.jpg` — cdart and back art are rare on fanart.tv, so almost nothing will ever be "complete". "Failed: 9486" just means albums where at least one fetch attempt came back empty. The 118 actually fetched is the real success metric — that's 118 albums that got a new art file.

The "Failed to fetch: cover.jpg" warning shows once but that's one representative line — the actual cover fallback chain hits both fanart.tv and iTunes, and when both miss, it logs that warn.

So Lidarr is fine. The real one is Slskd — it's in `HOST1_DAILY_RESTART_CONTAINERS` and presumably `DOCKER_UPDATE_TARGETS` but the container doesn't exist. Is Slskd gone for good, or just temporarily removed?


Slskd is slskd


Case mismatch — config has `"Slskd"` but Docker expects `"slskd"`. Let me find all the places in host1.conf that reference it.


docker ps -a --format "{{.Names}}" | grep -i slskd

Confirm actual Docker container name


slskd


grep -n "Slskd\|slskd" /boot/config/plugins/varaverk/Configurations/host1.conf

Find all Slskd references in host1.conf


56:#   DOWNLOADERS             slskd, SABnzbd, qBittorrent credentials and URLs
277:        "Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index
571:# slskd — clears stuck searches, dead transfers, purges expired failed imports.
575:    HOST1_SLSKD_FAILED_IMPORTS_DIR="/mnt/user/Temp_Storage/Slskd/completed/failed_imports"
753:        "Soularr"                       # Slskd automation — background only


Just one instance to fix — line 277.


275	        "Dispatcharr-Basic"
276	        "ErsatzTV-Emby"
277	        "Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index
278	    )
279

        "Dispatcharr-Basic"
        "ErsatzTV-Emby"
        "Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index
    )


Edit

"Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index

"slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index


The file /boot/config/plugins/varaverk/Configurations/host1.conf has been updated successfully. (file state is current in your context — no need to Read it back)

"Dispatcharr"               # Live TV scheduler — degrades without daily restart

-        "Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index

+        "slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index


Now check if `docker_update.sh` also has a hardcoded list with `Slskd`:


Bash

grep -n "Slskd\|slskd" /boot/config/plugins/varaverk/Media/docker_update.sh /boot/config/plugins/varaverk/Orchestrators/*.sh 2>/dev/null | grep -v "^.*#"

Check other scripts for Slskd references


(Bash completed with no output)


grep -rn "Slskd" /boot/config/plugins/varaverk/Configurations/ 2>/dev/null

Check for any remaining Slskd capitalization issues in configs


/boot/config/plugins/varaverk/Configurations/host1.conf.bak:277:        "Slskd"                     # Soulseek connection drops after extended uptime; restart refreshes share index
/boot/config/plugins/varaverk/Configurations/host1.conf.bak:575:    HOST1_SLSKD_FAILED_IMPORTS_DIR="/mnt/user/Temp_Storage/Slskd/completed/failed_imports"
/boot/config/plugins/varaverk/Configurations/host1.conf.bak:751:        "Soularr"                       # Slskd automation — background only
/boot/config/plugins/varaverk/Configurations/host1.conf:575:    HOST1_SLSKD_FAILED_IMPORTS_DIR="/mnt/user/Temp_Storage/Slskd/completed/failed_imports"
/boot/config/plugins/varaverk/Configurations/host1.conf:753:        "Soularr"                       # Slskd automation — background only


The `.bak` and comment references don't matter. But `HOST1_SLSKD_FAILED_IMPORTS_DIR` has a path with `Slskd` — let me verify if that matches what's actually on disk.


ls /mnt/user/Temp_Storage/ 2>/dev/null | grep -i slskd

Check actual directory name on disk


Slskd/


Directory is `Slskd` on disk — path is correct. Only the container name needed fixing. Commit:


cd /boot/config/plugins/varaverk && git add Configurations/host1.conf && git commit -m "Fix slskd container name case in daily restart list"

Commit the slskd case fix


Error: Exit code 1
The following paths are ignored by one of your .gitignore files:
Configurations/host1.conf
hint: Use -f if you really want to add them.
hint: Disable this message with "git config set advice.addIgnoredFile false"


`host1.conf` is gitignored by design — sparse checkout keeps credentials off the repo. The fix is already live on disk (it's on `/boot`), no commit needed.

The warning will be gone from tomorrow's daily run.


(orphan image)
stopped    Image ID: 98713d057a64
nandyalu/trailarr:latest    Created 9 hours ago
(orphan image)
stopped    Image ID: e3b1d8b3996a
lscr.io/linuxserver/code-server:latest    Created 16 hours ago
(orphan image)
stopped    Image ID: 7ef030770f02
ghcr.io/fccview/degoog:latest    Created 1 day ago
(orphan image)
stopped    Image ID: 8edb676fd7c0
bitnamisecure/redis:latest    Created 1 day ago
(orphan image)
stopped    Image ID: 0376109b5a94
ghcr.io/mescon/healarr:latest    Created 2 days ago
(orphan image)
stopped    Image ID: 7478276f7d91
lscr.io/linuxserver/emby:latest    Created 2 days ago
(orphan image)
stopped    Image ID: b08c127620fe
collabora/code:latest    Created 3 days ago
(orphan image)
stopped    Image ID: adb9927aa9a3
lscr.io/linuxserver/prowlarr:latest    Created 4 days ago
(orphan image)
stopped    Image ID: 25e4d1d04795
lscr.io/linuxserver/lidarr:latest    Created 4 days ago
(orphan image)
stopped    Image ID: 7ec7b398a57b
lscr.io/linuxserver/bazarr:latest    Created 4 days ago
(orphan image)
stopped    Image ID: 4bd29e98c23c
adguard/adguardhome:latest    Created 5 days ago
(orphan image)
stopped    Image ID: 2bce17d34df2
lscr.io/linuxserver/nextcloud:latest    Created 5 days ago
(orphan image)
stopped    Image ID: 95a9027a3f06
lscr.io/linuxserver/mariadb:latest    Created 5 days ago
(orphan image)
stopped    Image ID: 07ee8af9db7b
nitnelave/lldap:latest    Created 1 week ago
(orphan image)
stopped    Image ID: 4a87c7d1276f
authelia/authelia:latest    Created 1 week ago
(orphan image)
stopped    Image ID: f092ccf87a47
lscr.io/linuxserver/qbittorrent:latest    Created 1 week ago
(orphan image)
stopped    Image ID: 8fe2590a575e
ghcr.io/dispatcharr/dispatcharr:latest    Created 2 weeks ago
(orphan image)
stopped    Image ID: 708fbdd98a28
jlesage/nginx-proxy-manager:latest    Created 2 weeks ago
(orphan image)
stopped    Image ID: 9a7cae7543d0
gitea/gitea:latest    Created 2 weeks ago
(orphan image)
stopped    Image ID: 7a4331f792b5
thewicklowwolf/channeltube:latest    Created 2 weeks ago
(orphan image)
stopped    Image ID: e8399ef26a0d
ghcr.io/cleanuparr/cleanuparr:latest    Created 3 weeks ago
(orphan image)
stopped    Image ID: 4a0a519c9231
ghcr.io/pansalut/koffan:latest    Created 1 month ago
(orphan image)
stopped    Image ID: 62b6a600bbf3
ghcr.io/laurensguijt/unraid-pwa:latest


grep -n "prune\|image.*rm\|rmi" /boot/config/plugins/varaverk/Media/docker_update.sh | head -20

Find prune logic in docker_update.sh


ugrep: warning: /boot/config/plugins/varaverk/Media/docker_update.sh: No such file or directory


find /boot/config/plugins/varaverk -name "docker_update*" 2>/dev/null

Find docker update script


/boot/config/plugins/varaverk/Docker_Essentials/docker_update.sh
/boot/config/plugins/varaverk/Docker_Essentials/docker_update_remaining.sh


grep -n "prune\|image.*rm\|rmi" /boot/config/plugins/varaverk/Docker_Essentials/docker_update.sh | head -20

Find prune logic in docker_update.sh


8:# Pulls the latest images for configured containers. Two modes: normal (daily)
33:#   Pull → compare → prune dangling images.
113:#     restart those that received updates, prune dangling images
274:        warn "$container — could not determine image, skipping"
288:    OLD_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")
298:    NEW_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")
318:# old container, recreates it (new image, same config), then prunes the old image.
345:    warn "DRY RUN — would prune dangling images"
348:    PRUNED_OUTPUT=$(docker image prune -f 2>&1)


(orphan image) stopped    Image ID: 98713d057a64 nandyalu/trailarr:latest    Created 9 hours ago (orphan image) stopped    Image ID: e3b1d8b3996a lscr.io/linuxserver/code-server:latest    Created 16 h…


The prune in `docker_update.sh` uses `docker image prune -f` which only removes **untagged** (dangling) images. These orphans are still tagged, so they're invisible to that command. They're the old versions left behind by every container update.

Let me verify they're all genuinely unused before cleaning up:


docker image prune -a -f --dry-run 2>/dev/null | tail -5; echo "---"; docker images --filter "dangling=false" --format "{{.Repository}}:{{.Tag}} {{.ID}}" | grep -E "trailarr|code-server|degoog|healarr|linuxserver/emby|collabora|prowlarr|lidarr|bazarr|adguard|nextcloud|mariadb|lldap|authelia|qbittorrent|dispatcharr|nginx-proxy|gitea|channeltube|cleanuparr|koffan|unraid-pwa|bitnami.*redis" | head -30

Preview what prune -a would remove and list matching tagged images


---
nandyalu/trailarr:latest 98713d057a64
lscr.io/linuxserver/code-server:latest e3b1d8b3996a
ghcr.io/fccview/degoog:latest 7ef030770f02
bitnamisecure/redis:latest 8edb676fd7c0
ghcr.io/mescon/healarr:latest 0376109b5a94
lscr.io/linuxserver/emby:latest 7478276f7d91
collabora/code:latest b08c127620fe
lscr.io/linuxserver/prowlarr:latest adb9927aa9a3
lscr.io/linuxserver/lidarr:latest 25e4d1d04795
lscr.io/linuxserver/bazarr:latest 7ec7b398a57b
adguard/adguardhome:latest 4bd29e98c23c
lscr.io/linuxserver/nextcloud:latest 2bce17d34df2
lscr.io/linuxserver/mariadb:latest 95a9027a3f06
nitnelave/lldap:latest 07ee8af9db7b
authelia/authelia:latest 4a87c7d1276f
lscr.io/linuxserver/qbittorrent:latest f092ccf87a47
ghcr.io/dispatcharr/dispatcharr:latest 8fe2590a575e
jlesage/nginx-proxy-manager:latest 708fbdd98a28
gitea/gitea:latest 9a7cae7543d0
thewicklowwolf/channeltube:latest 7a4331f792b5
ghcr.io/cleanuparr/cleanuparr:latest e8399ef26a0d
ghcr.io/pansalut/koffan:latest 4a0a519c9231
ghcr.io/laurensguijt/unraid-pwa:latest 62b6a600bbf3


These IDs still carry their `:latest` tags — let me check if the running containers use different image IDs, which would confirm these are genuinely stale:


docker ps --format "{{.Names}} {{.Image}}" | head -30

List running containers and their images


Immich-Gmer4Lfe ghcr.io/imagegenius/immich:cuda
Seerr ghcr.io/seerr-team/seerr:latest
SABnzbd-Gmer4Lfe lscr.io/linuxserver/sabnzbd
Jellyfin lscr.io/linuxserver/jellyfin
musicseerr ghcr.io/habirabbu/musicseerr:latest
Sonarr lscr.io/linuxserver/sonarr
Radarr lscr.io/linuxserver/radarr
claudeclaw ghcr.io/paulmeier/claudeclaw-container:latest
VaultWarden-Gmer4Lfe vaultwarden/server
Redis-Immich a8ac849d98ab
Emby 2540ebc77f81
EmyCredits-Ocr yock1/embycreditocr
Fetcharr egg82/fetcharr
slskd ghcr.io/binhex/arch-slskd
SeerrFin 7e913cab7edd
Soularr ghcr.io/binhex/arch-soularr
NextCloud 543d3ca24f72
Readarr ghcr.io/binhex/arch-readarr
Profilarr santiagosayshey/profilarr:latest
Pinchflat ghcr.io/kieraneglin/pinchflat:latest
Organizrv2-Gmer4Lfe organizr/organizr
Dispatcharr-Iptv-Users 4c0b06538989
Dispatcharr-Basic 4c0b06538989
Dispatcharr 4c0b06538989
Code-Server df1550b3c1b8
Trailarr a0991f0faaf2
Prowlarr 7b41e8fbe7d2
Lidarr 77e08f22262e
Cleanuparr 99ce15758126
Bazarr 48328fb82fc3


docker inspect Trailarr --format '{{.Image}}' 2>/dev/null; docker inspect Emby-Gmer4Lfe --format '{{.Image}}' 2>/dev/null; docker inspect NginxProxyManager --format '{{.Image}}' 2>/dev/null

Get image IDs from running versions of updated containers


sha256:a0991f0faaf20fb022fcde3b66c040a9c9706cdb95cc232b6648fa85dc9d2a7f

sha256:081041ba9c43c3489080f2a65dbea1892a11aa10fc939ec2983185918e5f3914


Confirmed stale — running Trailarr is `a0991f0faaf2`, orphan is `98713d057a64`. Running Emby is `2540ebc77f81`, orphan is `7478276f7d91`. All different. Safe to remove.

The problem: `docker image prune -f` only removes untagged images, but Unraid retains the `:latest` tag on old images so they never show as dangling. Let me clean up the current pile and then fix the update script to explicitly rmi the old image ID right after each update rather than relying on the prune sweep:


Remove all 23 orphan images by ID


Untagged: nandyalu/trailarr:latest
Untagged: nandyalu/trailarr@sha256:16cfa0f23762db7881ff89a1f89b856406574d045893a268ec8d8d0b6c775eb2
Deleted: sha256:98713d057a64446665e612a547f0351af001e0d3500d79cc07a2285953180213
Deleted: sha256:ecf2f378192df6b6116454f059f9d18cb04766b04dc3765121109b407f5ee1d8
Deleted: sha256:3b5fb35c46415be8d55b6f82d8cc58a3b049a289f1bcbfaa49a9f83b4c3a01d6
Deleted: sha256:9649c294e5a64146cae5bb1e21bf9646a215de77f0ed7766e4fe80572dacf5d4
Deleted: sha256:e042df254bfae53b01ab042a004386f5f164efb1f88b78bdf4e20cd1a6d41d12
Deleted: sha256:e58a8cfc3000d73a736ff30bb46aeea34d46facbee43e4964e84d97dfc43f969
Deleted: sha256:72094a7281d998a86703e651700d9503ee743699d3a69ce021995ea3c6124843
Deleted: sha256:3133e422020326e7d1d36fe19235d518917f9fd3908a9013bc90f51e3d7773b9
Deleted: sha256:9b179942f7014d8ef7d95bc83c1f87950a93cd83f4af924af5e190e7962868f5
Deleted: sha256:5774a8cc49664f3a1c33471c79edddae91e3d8737636d9257318482f2e077ffa
Deleted: sha256:a53816326969a3e42db0d5c5d4410438686ad3e6012a405977f51b1a477f1b4d
Deleted: sha256:d83e03980d4ffbd0de719b3be47de9897eaed4814688ec14a9864b82695e9f06
Deleted: sha256:77bff013c6ab2b489b61ed5de4ee22be4d69f75b0c5e4095d3b524f5b79ed1e8
Deleted: sha256:e5d1a381ab1ee45689ac2bdc339f8539a177aaab4ffce3e970b997dafa1c2eb0
Deleted: sha256:71cef843d17d94227a5123e79ec3a6075798c2e0d7c31e81233e25b257f9f472
Deleted: sha256:1b1c5a5fe2169d116499405ef3f5195d60df3aa2c75695fe8e7b60d448e563ac
Deleted: sha256:1a293b3c2da6dfa4065d1c111ae2914bbe862fd0c6c9007f51bfed37f56a7bd3
Deleted: sha256:3dfd72fec241118005f59a0678831716f2b57cd8d0c4aac2857429b7cf6297e8
Deleted: sha256:21a1fecd33f1a2c9a21d76224e2847ecbd2325fd2d3cb46a91e465427c298a88
Deleted: sha256:d4934f288e40f2257bc648a76c3fc1ae4adb6dfd2f4d967b7c618d048317c2d1
Deleted: sha256:16c4ad3ccf74249aed8e3fe8c33b6b243904fd3cd4d6e2c31ef5d9d65bc3358b
Deleted: sha256:f5019d0a82688d9e9376eea90bc87b528ba8b02787bf438053cb432ee051a662
Deleted: sha256:1bad29fcf896544991e62a36615bac7a0d9c8726e10550223eadecf60597c0b8
Deleted: sha256:fc41e6dcea29250115c2861cef271bc0057115737aed836f1c840da2a2f4668b
Deleted: sha256:91669ff72d023d1f488f01de7f5500dfee02d64073483b10f22050763e428894
Deleted: sha256:022897182815b9bbdc77b5197fae84625f3c995abb70b1b093e589db627f4c77
Deleted: sha256:c325626c26665675261863d3e8d48ac48fed73d5bcbf77a32f5c01a9975c2432
Deleted: sha256:6d4f99e940d0aada37025d116243b008a8b6de9904e25e00ae56e84c8bc74645
Deleted: sha256:2eb6bb6a1a86777371ae3292c9f538fe80f5d81e341e0b89d21bda40d997a7a8
Deleted: sha256:eedfdaa1218cfbd0ca931b8eae1b6354ff195d4edbebd4c5bdbdc472ca43fe58
Deleted: sha256:4fd6dee5accf24689567a9883461f415cc8e1a3eaa0a5817b5029cb8a4ea2e29
Deleted: sha256:d04b9c428a5bab3bfe18e0deba9a39033e43103f5b9f482a4abe9c3f5d7d8a6e
Deleted: sha256:e330bc2d793c553791a296e21fb42cf4866a0d4a70ff988e146e50434ea31ad2
Untagged: lscr.io/linuxserver/code-server:latest
Untagged: lscr.io/linuxserver/code-server@sha256:cb261a7f87674b445e0fd66d87d55900c1b823d276c727ab0d168a75e69e9992
Deleted: sha256:e3b1d8b3996abb59b6adc5a6189112632559a9bfdcd246c83519cdf8abb6547d
Deleted: sha256:c3450d7e9e47bf599ec410124d1c5824a0f6c44fd6091dc128f2f4cd05745156
Deleted: sha256:72a668c5d0f72d57d068ab03b9f47509c8d4c8026c94b7afe8c5a70a06fe8837
Untagged: ghcr.io/fccview/degoog:latest
Untagged: ghcr.io/fccview/degoog@sha256:84a2b6197df3dd54ba512a1d816333fb48223dd218d666dae9437fb380af5e25
Deleted: sha256:7ef030770f027d5f8fd082b0f0a1c0d08f5e5598541587ebe78a0fa5f4cb3ba3
Deleted: sha256:3e7438c932d2ea3afe764e679d927cb8ea1c875b26c8a4ee55023b301b847602
Deleted: sha256:6ba039d43865690bba8563046a1f87824bb252eca7e5ee6d6ef54cf5dcf61019
Deleted: sha256:09d3cbfc5ebd1138c0a511a3ea2f446308f8d02da8fb91973792d35e7ce61c5a
Deleted: sha256:6feffd49613dc34ebef91bd5fa23ef66cb5cfc10999b071508492acf92057cbe
Deleted: sha256:5a9368ea45e44fc67c08c5901d38980eb2da5c8c7a9d999782d78b2b4166fcad
Deleted: sha256:b5bcaed4d4901c61300c639ef9cea715462efcf489fa63306ba464503ebdaeed
Deleted: sha256:cd9366c9104c9540b4f0b69a8e2c5306e4e1667b2d451c48ebeb30338737fe4b
Deleted: sha256:9b6ae4bab8ac79544bdbd56ceef317a3efd656e374d35f772a446f5f82f8c7c4
Deleted: sha256:14575d1b83fece83a3f35f7bb737047f655a5ac9ded10ac806920d5703a89671
Deleted: sha256:a296028d5a1f990e077949e4f9c6450fec9f5ff06f0990c6177aea59052816e0
Deleted: sha256:4fd4f5fd203b9e291075493cc1d4996575f30e340dfec71de81c3df95c801cfa
Deleted: sha256:9dd9d27038a92a08f130c05012690a943757b848f787b0124d98764fd9404073
Deleted: sha256:a52d00c1e31db13509bd5dbeeaf54fae37adcc12e1866a923f106e019a3995da
Untagged: bitnamisecure/redis:latest
Untagged: bitnamisecure/redis@sha256:6e7a020f1f6504698a7272c58783bdc2c23588c49febbae5aca1bb8dfa10af25
Deleted: sha256:8edb676fd7c0cd4098712cc06a9c0a5cd0e65c2a6015064f61a2b3747e569335
Deleted: sha256:6ccc759e403e9ea6f8a58369449f5af52f6fa7b8815953a1a6d0e837afd8f923
Untagged: ghcr.io/mescon/healarr:latest
Untagged: ghcr.io/mescon/healarr@sha256:c2c36473c4b3d23536f902cc2e0976007994d881930fb5144db35840756bbc6a
Deleted: sha256:0376109b5a949b270087a1b8bf308f3645459b4f2bd75f3777c1068e4ee5db47
Deleted: sha256:ea8162d46ed0b2410dbe67fef73eac68e20d4a0e0525b1bcd0d37172511fe6c7
Deleted: sha256:ac7bd894ae116b20fec22515f88c2a49c906e879b99d12e89c649d13d304129f
Deleted: sha256:ab510e696ad289404fe8f86af89df8d810c97a9843fad00bb091bc9fcb46a8a5
Deleted: sha256:6bf8c3460900cc2e9a98f7420bf24e56990b1125c87e0446e0e26e03fe36a772
Deleted: sha256:47fd7afe42207fe89cf7494150d51aca84843369185a428ad44441f8363883c7
Deleted: sha256:c8b718f049e36c5294e95bca52ce8fab631ad94ba1105531ef935b6e8b142849
Deleted: sha256:80e9ee62987ebb933381a366fee31aed21153a871af256b7362f12d142fbfe46
Deleted: sha256:9d80a1d6b2a8877091a2d7397f8cc95a874ddd6a5b1f3dd4582e3ddabc98f473
Deleted: sha256:b2008ac19409fa6fee4b52596271400498aebd0be04dffac5351bd1dcf230f2a
Untagged: lscr.io/linuxserver/emby:latest
Untagged: lscr.io/linuxserver/emby@sha256:e9ec0591ca9a74b93aeb6b1106963400cd2fe5e924d57520520fed393a731a32
Deleted: sha256:7478276f7d911a91490a76a98437e86e9d8159a0f10bc291754679bf255ac586
Deleted: sha256:329f6f684bcced5217a3a35f83bedd8a37375f16d72ec6691160c48318a6f755
Deleted: sha256:b9be7885ed962126d8836c174e9b4ee1d2a5545174ecd239bbe9ee971ca68570
Untagged: collabora/code:latest
Untagged: collabora/code@sha256:e42a50e71d5085a2602eed115bd820b87e713e703e87efab91543440efb3698d
Deleted: sha256:b08c127620fe0e07c7cdaf59590271cb4a913b4308a43906c756aab59f7b4341
Deleted: sha256:735e403cb7001bafdde0780a7dd1100f9cd458b5944dcd2803d9d294866caffc
Deleted: sha256:397c30134a85dec206f2681aadbd866b641a8a3e9518a299222b1396703ce8ee
Deleted: sha256:7c5d556ec615429c15a889e38cb47a65ed6c04cb3ada4dd8d9505f752bc94c90
Deleted: sha256:2dae416d5869ec6e66827ace3b2c0ec58488d053913af26a4a71032686cb6aa2
Deleted: sha256:8c68498cf93383b6f647802f8759a1a9271457ed0df302d4bf0924dd3b20b7d7
Deleted: sha256:d4e3a0f101857711b787d6a0391eadef669a22d33ea5cb3bf27883413776d28c
Untagged: lscr.io/linuxserver/prowlarr:latest
Untagged: lscr.io/linuxserver/prowlarr@sha256:2489c6dbaf11e3a6d71aeb2e6980d04193d4af611aa7064a974851222fd41722
Deleted: sha256:adb9927aa9a34357e5027510de15b6ac2e1f8c5a70ce9f5606c76fb8f5b9251e
Deleted: sha256:1662789579002e4e9188f96f87d639d2a5271609ae6b98fa4ff404516a50b292
Deleted: sha256:5a3eb6fcc69867ffd902f7d2cca3848deeb16df29f6d499777928f05e78693fe
Untagged: lscr.io/linuxserver/lidarr:latest
Untagged: lscr.io/linuxserver/lidarr@sha256:b08b2194fa4ddb7f7ace9d1bfd82bd9b26f457d79aa70f42d923d2e15a820f0e
Deleted: sha256:25e4d1d047959c8e933cc5de3c88c5af04309daef42717873e57e1731c60a5f6
Deleted: sha256:a5bbd99bd9a778aa40231c87820c3b2d5305f60b7ab372b01930ca788eeb634e
Deleted: sha256:dab014001ab79088aa1f0552cb4f55622a29338b415311804a91023bfc0152e1
Untagged: lscr.io/linuxserver/bazarr:latest
Untagged: lscr.io/linuxserver/bazarr@sha256:4b5e510042bf471c8bafab89cada9774fba2fb25f16ec64235151cacbe847c10
Deleted: sha256:7ec7b398a57b324e24daf9fe8cb0dd1b08894bfcc9ce37427e92b67e67ae379c
Deleted: sha256:d303c8594b60b2bdbbe03e0dbfb1176a38e96416a89263a3aff39149c16208f7
Deleted: sha256:4eecd3d018aa1ef245e7a7890bfbdcac9c32ab280b47b9e4be7c4be56c83663c
Deleted: sha256:b72ec0594a6586388cb39300c1e135120681d21c2cd420e12fef6735b8d47fc0
Untagged: adguard/adguardhome:latest
Untagged: adguard/adguardhome@sha256:e6f2b8bcda06064ab055b44933a4f0e983c35558b9cdb8d2e7ab1efcee36d890
Deleted: sha256:4bd29e98c23c15060696b0503b60864023ecea76c0bc71a4e6ae2c3c2b71348e
Deleted: sha256:baaca04ec86d82a65eba39a80b5a67699f2c81909f05665cca9c17f10c69fc18
Deleted: sha256:031a64359129d9726ceaf45a87be82386579e04fe1c5012ca93b84ffc401bde6
Deleted: sha256:8e9dc4a62af4f130b91acce437c305762217fc63b53e46827a089f40a01a9938
Deleted: sha256:2074eaa4bf82e0d0a76efa94377ef1a6c036a1a111a9920cd282f141a4f6b3a2
Untagged: lscr.io/linuxserver/nextcloud:latest
Untagged: lscr.io/linuxserver/nextcloud@sha256:3beb1716beba8cff05b1f13d9122cc4180aacbecca7dcc6fe281a6d054cc6835
Deleted: sha256:2bce17d34df2639050212dc45db7ba841dbcb88cead05b8e81a8eecb8cc9fe12
Deleted: sha256:354f9cb16aedddf730e476c58d225211ef8995b2f566eb9ea65edf9ffffd113c
Deleted: sha256:b922ad9120b1031f4109ba33ff7b14358e0587456ca37eb09705ecadb671b64a
Deleted: sha256:eba92bfa1355ae1b9af5b8180ec0b995e4f4535b923b9ae14e83e95862920d29
Deleted: sha256:a3cb2168f7144ef84e654323865cf9c467a86b935e5ce7d7d690b38480487ec5
Deleted: sha256:11fa5ce1f26e7f5b3ac75ceb3dcc0c8631e23115eb79955253685c37fba1d994
Deleted: sha256:d6a7b0434dc420b3d4dd02b6640b3860845111975fcc9c4a2d1a0334915b7a29
Deleted: sha256:d2f8550ea6759b34c56285f3d476c6c50fb9f316877e7a5afb14e57199d7350f
Deleted: sha256:943ef14c040f6490623dbcbe1c97f47d629d34bdf6f493ed9f79bae29b1ad002
Deleted: sha256:f1240da4083c64ba6735edcef7a27223223e01547ecacd9b1bb1d46982c5de41
Deleted: sha256:16e133b3467e076c393e11201798e0fd8ca2875bb6bde235d3e56ab4ee8b47a8
Deleted: sha256:e8ba60b9e61a329cfd8beca125b6230e59b2ca375259842fcaa6f7243723a2e6
Untagged: lscr.io/linuxserver/mariadb:latest
Untagged: lscr.io/linuxserver/mariadb@sha256:adbb0142f55abd0e913b8fdd017f637d2318d434e74755908c768399e96403ec
Deleted: sha256:95a9027a3f064435a3b20e2e2c9cf325f6a61272ca925a93e9c08d3bf3f3496a
Deleted: sha256:68353f30be84f210357ed04754ea70b53bd72c1ed9fa58580754e3fc58917c57
Deleted: sha256:05f0cfff1b903cdcfcdfbab61fa0814a6a880e5b6f8ddfe55e4e03627a9527de
Untagged: nitnelave/lldap:latest
Untagged: nitnelave/lldap@sha256:bce90cfef8f13c59f74386376a9b541f4e214170eebecc73f8ff7c1f7a375a87
Deleted: sha256:07ee8af9db7baff7d0f72ffcf3ba9b3819730eee869363e13e4236a24c92db2b
Deleted: sha256:6af8c66621df35d55a420093deed3554e808773cbd9efdc068113084e2a4f5b3
Deleted: sha256:7d3bceb7656c3521c02fb88a64cbb98ab5eaa4d82ba41317fab9d17e94125748
Deleted: sha256:0ef71930436ac978a2707df95ec9f655c0c9f7c95a985a3f82aafa0715866656
Deleted: sha256:bb7e062f7549ef30aff63c6d55af26f8cb14430c3eeefb5283ad2b268959938e
Deleted: sha256:1b5165dc61c5b7a19fc35feb75405a11422d46cda1ead16f7ac6c45452635d90
Deleted: sha256:74c6f1bf60087c08471bd59d7318a72d577bcc58db8268dde79b64270d2d101e
Deleted: sha256:ed9a657a010e5db9461368fcbafc6da6997853c647cf18f586faf85e0c21432d
Untagged: authelia/authelia:latest
Untagged: authelia/authelia@sha256:1b363e9279e742397966333f364e0876ae02bf5c876de73e83af6d48c57ff51b
Deleted: sha256:4a87c7d1276f351a9d2b2139a676bb9aba16692825c858523c9c002744d0aa59
Deleted: sha256:3d9bdfe815fb88b461e4c53ae18c948c2395f61fb70cab6d333a22e4c2bdfa21
Deleted: sha256:c3ca8f93573c2a18ddc064a6e2513c3157e1ce104ab1255d8e9eb72d114ce7c2
Deleted: sha256:3fa38ddc53a01bef495223343313aef16dfa5d4a8e43e55a2694c947ac5b365a
Deleted: sha256:5c5ceee899656979ffc47cc3a7c6b779f1a8f16d8ed164cd12b333543573b073
Untagged: lscr.io/linuxserver/qbittorrent:latest
Untagged: lscr.io/linuxserver/qbittorrent@sha256:715d2bfbcf1cd3d734cbbd4fbd599eb7ea0642eaa079a372dd0d343f59516700
Deleted: sha256:f092ccf87a4735d7c0e498915cc92a03167f74b01f95c7261e54c2e834a56f47
Deleted: sha256:9498590ec2e379cbd845a115eb26fda0bdcb285e7d6ed5fb8b30223a16d24d9f
Deleted: sha256:6cf62e6a1b93286e8e7792f8eacc7c5b6004aa74a356920e326a84e1838ce076
Deleted: sha256:efc06a218d58ef185aa4ff46816c2c62482519ed76a148afcafe49e6344d25d7
Deleted: sha256:730546c6424da57df383db8a7ed5de1bd590be1e6dddceaaa63b3b95fcc6af0a
Deleted: sha256:b450930764cc09ef690b7993c7e0b349cb6526d66aceb81149c60c35aa6d313d
Deleted: sha256:51bf94d2b7db3cb878ceffa956b760f50d9c106ccead8cd78fd8411d42020c28
Deleted: sha256:4fce14ea3209fe3c47c21d1a527ca6830f5ed20b9c83665cc521fb2ce81a260b
Deleted: sha256:b9757ea7be62177e349cc95ed91c79f70aeb00e9807389e394d917b0ba2802a3
Deleted: sha256:118ab51a90b27e9c66b720a12b866f4aa13b4b0d4ee1f24afcdde2912fedcfad
Deleted: sha256:0bca215c74edf55a239c553b1b56e6b35a3e15d669faa7d5220aacf453cfa9b1
Untagged: ghcr.io/dispatcharr/dispatcharr:latest
Untagged: ghcr.io/dispatcharr/dispatcharr@sha256:2bdcfd9dc113e743ccb3ea424e75e19b2281309b05a7d649c3717471b9f70f03
Deleted: sha256:8fe2590a575e112d2896f7ac877e9bf94c3260247009c5bb67f761e5f7dea8ab
Deleted: sha256:f1567cc36c85c3eaed45878d241cf9e1b91a94ed3cd318eb29cab583abc813ee
Deleted: sha256:4545870dc83de96d55768c6038b58db044e5310d0b37acd653f602836afd4461
Deleted: sha256:03e260578226bd06ffe0962280a1acd418a7f127586e2093fe36220a53a7b787
Deleted: sha256:dcad0b3464f79183efe5ac5b7f2843c4820013a96ba25b93fde54d91410d7b82
Deleted: sha256:6a1b85c48ee0af9941e35ade93b24a16918ee8ac9a23faebb6c7246d505bb73e
Deleted: sha256:a49a9eebf7bb5441fa3b6c5e7a9708d905fedaf6253edd8e9c6f322a36414ff7
Deleted: sha256:9daacc9d72b3360c57b92cfcbf7c966b985b434468fefa4b636d0bb775d90ad0
Deleted: sha256:3357c58aac68a235f597dcc5b2972efdc5bf3f285aaf536fa9b413b485302186
Deleted: sha256:a2e9ce5c83cae29f31bb711f8b086377306879eb1283b7ab2a56564fcafab6a4
Deleted: sha256:da3c18d384daa28637f8508ac6bd4a3a334dba4a90aa2f3527f18895cfe57c3d
Deleted: sha256:4386c2491671320e3d0e8f1e88a63e26a1f5a2b9670f94bdebffed6829f7daa7
Deleted: sha256:306d7ed56d58e47a03d089bd6bf7dec34dd889a76c779fa0eae84aecf62ad6d1
Deleted: sha256:489b53c84cccbe8802934633fde14dfb768c3310c80c9e4714a8ef842ae4752c
Deleted: sha256:07727c3cf4b725d43793a99d83ef4a01aa73c0036c267265dad008056a87616f
Deleted: sha256:37ce6ebe52a2b66ee4fa46c58220004640aa4dacb020aba4385057641b4dbdb2
Deleted: sha256:2e23bf169a07072a3019ed973a165cfd459de1418b6afdb81ba629b4405717ab
Deleted: sha256:0947b0d0281409da16adf042e7973471c2c70f418ef7352b0e8c1add9e181a86
Deleted: sha256:b2f37e21f02625786a331ad7f3ca190d290d7cbfb9d1d18051b738b7cd7df9cd
Deleted: sha256:15ef2cf2bc1f773bd0678d8b8cc2fd836cda3bdcfcb6b06d3eb9914784713105
Deleted: sha256:b85413833825355cac5f4dacabaa0c7026a5c8f81389c1c83a7b80a54be96989
Deleted: sha256:8ff74afd4517256584e611389cd2f802e7fd7b2aab519b33d2a70db2bb178e89
Deleted: sha256:d1b7dc61bca84f1e0e62403299f0d509c261a99a7cda4430c6423f700f38b8d8
Deleted: sha256:df52772b4c256bc81ef4ddacd66cc30b998b2248125116d3f3e225bb7451d79d
Deleted: sha256:0d641921b271966298fd25cf0bf82cb8b787d0bfd23b4274f66d2c5f4f819fb8
Deleted: sha256:3d52c9be7010d2226e1de9d6c3427c73a6429ead878f1bcbc58c6d350e16d80a
Deleted: sha256:28b89179e97b6f1794fc637315bb364dc948e8049cbb1aafeb6cc364faecbf5e
Deleted: sha256:5fe9baf8b0148882812e5071d5cb902ab2fdcac7ae582a2506b347be6067c32e
Deleted: sha256:8a519c358c5a2f286bce4f4e5fe98f21c47b14d249b57269a765fff5707b4fe1
Deleted: sha256:2198cf6dab8b6b813214061b8b81febd09f09810e3d85fd06f41b2cf61f91e11
Deleted: sha256:7ba8996cdad3825bc06eac0dad7f5078471e6361a37e598726b59980b687e6e5
Untagged: jlesage/nginx-proxy-manager:latest
Untagged: jlesage/nginx-proxy-manager@sha256:ee1db8ddfda580df3a87b53aae4e954340251ce0b3eb9008cd51d37ad307bc35
Deleted: sha256:708fbdd98a28a8b9d00caafcfa3beb2a7f343e9082ec7ce57f5109cc99835746
Deleted: sha256:2fe03415c1a8eaaf4745416a7b3cc60bd692b9b0e8190e78670f8eb1a91b04f3
Deleted: sha256:577e153cd2f2cb62c6e14e43bd4aaa108e0fc3932bedbd0709fc2f05bd512961
Deleted: sha256:7729aa47550f85f590609153d83cc4db2164ffad78198dea6bae738d3d808e49
Deleted: sha256:268cf0041481a54542ba0c0e04d02eaaf078ce5003954a3d3ef9413db1428d0c
Deleted: sha256:0a4ef6f2031c9b6494a95077b07c6fa8fcaec90990aefe984a66780c13e6af29
Deleted: sha256:c13470dff57255ce70c24482323bc4adeef173d60e3386434d5527ba531e4bbd
Deleted: sha256:ae9566b7bfc787c2b99908118a1c6e82d36ca779d3bbb5a73197c772b2bd9478
Deleted: sha256:3c1d1179d0de8eaf7201a909524a99f96e6a43b02e4d3009e6f5cd4a435525d6
Untagged: gitea/gitea:latest
Untagged: gitea/gitea@sha256:7d13848af12645600a5f9d93ee2560daa9c6fa6b5b859b7bff3a5e1c0b661031
Deleted: sha256:9a7cae7543d0c6d6dc63465fcc4dffe39f193a5ec4a629b49ae9f326a2dc22cc
Deleted: sha256:480f54f248eec9532efb568a64a1e714cd3e8f97947aaf321ee801b6b0c6a58f
Deleted: sha256:b45e9d49702cbbc6feed33842b316a9b9223aacd514884ea0d2254866dc6c602
Deleted: sha256:0e5d00e946e9d9a34dc03a298f6357ce32c6a7fd022c17e48fe099fe36253206
Deleted: sha256:899fd7066ce85784b56fd888bcea1dc2b4966fad0c0200a3bf5a415af9be60ee
Untagged: thewicklowwolf/channeltube:latest
Untagged: thewicklowwolf/channeltube@sha256:62adc8457812d1d081ad1c5c50c97010511b1a489a4da0f39704275457f33b4b
Deleted: sha256:7a4331f792b5fa33301f811847888e0bab9629ea06356ec43f42a633a427d942
Deleted: sha256:97e1198d5974661a323afeb2c17aeba62b0b786f77716a7592ca7e49032908fc
Deleted: sha256:5ff728faf96b830fa38f5671c83db669a4818f5c80d45c56659f5ee28a5c899c
Deleted: sha256:4333d681530ed0ceaf83829ab447f59546616fa1f333329e2e0f67482a2196d8
Deleted: sha256:a90283fdb726bcfca0fb08a8517670a415e2cd324420561692a2fc665c57e06c
Deleted: sha256:a832c028ffa8c108ee3fb4e870380a1eea7acbdbd292e9391e7f85bd6125c74f
Deleted: sha256:6181ab99cb635421df4e4b7aa9f082d2caad190add18183740bceff40b05975a
Deleted: sha256:1994be473d9d9b9c3cabd2d9b0579c8d114c2a6dce1c51586536aad4e6cb5bbf
Deleted: sha256:0b7d3deaef71d9dba69c2ec71177fbe8845717e20f8b25c994cf4df747f54d0e
Untagged: ghcr.io/cleanuparr/cleanuparr:latest
Untagged: ghcr.io/cleanuparr/cleanuparr@sha256:4ad626da7e1d2774ca51bbfa812f832d5639264b3fe308909e47de02ba2188f7
Deleted: sha256:e8399ef26a0dc4a2bc4cb69478ae7d910b61d596843e55eba1884a9e503e7811
Deleted: sha256:9d5826388ddb5bd4d4b8173f55a134c77655c11c3e2b892e97d792ac5f6d597c
Deleted: sha256:2240ced9003353241d71e65480fd3935a4b36bfec80afc3b0c4b96d36cbde73c
Deleted: sha256:289d4b8c0e3a52d73ef0ecb022453a7e4e397ca1eb75c54a429e0f234bc4fa50
Deleted: sha256:bf8f320aedb92329fbacd56af8fad7afbd202fa3f6d8450310bd92cb25d68959
Deleted: sha256:96e82ef03de8e8ff2defeb86f23104779d430348c436ca55e7416476c9c1c934
Deleted: sha256:d5d9c68a9a2477b67ce472db2f530e23658906b9dec0421c29705fe1d702f8b2
Deleted: sha256:32876e4c95dca7164508bf8e23e517cf3a6eef9ee39adc8a6070e7bfc6c54838
Deleted: sha256:6138358cee746347f915f5a266749593cabb74865d6e60139999d27fdd38ea85
Deleted: sha256:317bc84fac07b3b83dacc4a56f5172d03b3e450ff25edd87ebc192cc46128e5c
Deleted: sha256:d3c63fff1d83a270064b1c7ba57059f745908f34b3e8dfc07d2513917a58f830
Deleted: sha256:a131198a69f259d2fd935f764433605ddf593e3ec2ee0cdcdb737e1cdc7c914d
Deleted: sha256:c94eeb6e7425e3426384222dc53249ae24b5453ee05cdaa5cd53b872958b9a95
Deleted: sha256:c46c311fcf1b3ce8366ddb1deecdf4653fc0a2a4c1cc9455fec6e91e665e07a9
Untagged: ghcr.io/pansalut/koffan:latest
Untagged: ghcr.io/pansalut/koffan@sha256:891987ce244c80d4b1b49e98335be1b5b5c803a5f9bb3eff3407c108558386c6
Deleted: sha256:4a0a519c923110684843365f6934b308c57d6a8b63e5d87fa91b63f5e3dae10b
Deleted: sha256:1e7e3f00aac81d0e14b75ee5d5840ec19b78ea3608cdaf90110319c72eb141c7
Deleted: sha256:15f68e28b2d7f24af60e8ed31748aada68b4d78569d78a9271f3313b65875647
Deleted: sha256:b6a93ab5d03f3bdbef3e6c092ed25bfb0941389878c05b898895bcbe42dbe70e
Deleted: sha256:8938af189fadcd8e5ad5ef3b0381e389369d4beefb06cea4638e54eb496b5c10
Untagged: ghcr.io/laurensguijt/unraid-pwa:latest
Untagged: ghcr.io/laurensguijt/unraid-pwa@sha256:d60a588e01e61979d9b5fccd857a0014b6ac7e4ee910b3ac0f4d35cb4c8d3881
Deleted: sha256:62b6a600bbf3a2f563189e2230791920136b5c26ac266ea9d037d7e720ace6ca
Deleted: sha256:fba759eea317f64d405f6da133bccdb5ed03f9ae4934279dd59995aa535a11f6
Deleted: sha256:96d7d46db20dc36c667e22fdf465ade72e37b12243850076c4c96b8cd218599e
Deleted: sha256:dace4b5db9e69cdb9c4d2dc47af8c03c2c938d20f15587fa4e166fa06eda0af7
Deleted: sha256:7c6ca95d1dfb4fdf6f29ffc53c80afc15ac96e14c4d9a460b6246545c179aa2b
Deleted: sha256:b7e8a242875f2ed29f93662327a14f7348b9e48ae7430458e7cdbf75a763f508
Deleted: sha256:6f4b346f15318af52174526aaff9324776dda2957c42ed8e669788d6d81302ef
Exit: 0


All 23 gone. Now fix the update script so it explicitly removes the old image right after each container swap instead of relying on the dangling prune:


285	    fi
286
287	    # Capture image ID before pull to detect whether an update landed
288	    OLD_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")
289
290	    log "$ICON_SYNC  Pulling $IMAGE..."
291	    if [[ "$ENABLE_LOGGING" == "true" ]]; then
292	        docker pull "$IMAGE" 2>&1 | grep -E "^(Status:|Digest:|Error|error)" | sed 's/^/  /'
293	        _pull_rc=${PIPESTATUS[0]}
294	    else
295	        docker pull "$IMAGE" >/dev/null 2>&1
296	        _pull_rc=$?
297	    fi
298	    NEW_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")
299
300	    if [[ $_pull_rc -eq 0 ]]; then
301	        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
302	            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
303	            UPDATED+=("$container")
304	        else
305	            log "$container — already up to date (${NEW_ID:7:12})"
306	            UP_TO_DATE+=("$container")
307	        fi
308	    else
309	        warn "$container — pull failed ($IMAGE)"
310	        FAILED+=("$container")
311	    fi
312
313	done
314
315	# ── Recreate containers that received a new image ────────────────────────────
316	# docker restart uses the image ID baked in at creation time — it never picks
317	# up the new digest. rebuild_container reads the stored XML template, stops the
318	# old container, recreates it (new image, same config), then prunes the old image.
319	REBUILT=()
320	REBUILD_FAILED=()
321	if [[ ${#UPDATED[@]} -gt 0 ]]; then
322	    for container in "${UPDATED[@]}"; do
323	        [[ -z "$container" ]] && continue
324	        if [[ "$DRY_RUN" == true ]]; then

    fi

    # Capture image ID before pull to detect whether an update landed
    OLD_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")

    log "$ICON_SYNC  Pulling $IMAGE..."
    if [[ "$ENABLE_LOGGING" == "true" ]]; then
        docker pull "$IMAGE" 2>&1 | grep -E "^(Status:|Digest:|Error|error)" | sed 's/^/  /'
        _pull_rc=${PIPESTATUS[0]}
    else
        docker pull "$IMAGE" >/dev/null 2>&1
        _pull_rc=$?
    fi
    NEW_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")

    if [[ $_pull_rc -eq 0 ]]; then
        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
            UPDATED+=("$container")
        else
            log "$container — already up to date (${NEW_ID:7:12})"
            UP_TO_DATE+=("$container")
        fi
    else
        warn "$container — pull failed ($IMAGE)"
        FAILED+=("$container")
    fi

done

# ── Recreate containers that received a new image ────────────────────────────
# docker restart uses the image ID baked in at creation time — it never picks
# up the new digest. rebuild_container reads the stored XML template, stops the
# old container, recreates it (new image, same config), then prunes the old image.
REBUILT=()
REBUILD_FAILED=()
if [[ ${#UPDATED[@]} -gt 0 ]]; then
    for container in "${UPDATED[@]}"; do
        [[ -z "$container" ]] && continue
        if [[ "$DRY_RUN" == true ]]; then


325	            warn "DRY RUN — would rebuild $container from template"
326	            REBUILT+=("$container")
327	            continue
328	        fi
329	        log "$ICON_SYNC Rebuilding $container from template on new image..."
330	        if /usr/local/emhttp/plugins/dynamix.docker.manager/scripts/rebuild_container "$container" >/dev/null 2>&1; then
331	            log "$ICON_DONE $container rebuilt ✅"
332	            REBUILT+=("$container")
333	        else
334	            error "Failed to rebuild $container — will be picked up by docker_daily_restart.sh"
335	            notify "$container failed to rebuild after image update on $(hostname)" "Docker Update" "warning"
336	            REBUILD_FAILED+=("$container")
337	        fi
338	    done
339	fi
340
341	# ── Prune dangling images ─────────────────────────────────────────────────────
342	# Old images become dangling after a pull lands a new digest. Prune here so
343	# they don't accumulate across daily runs.
344	if [[ "$DRY_RUN" == true ]]; then
345	    warn "DRY RUN — would prune dangling images"
346	    PRUNED_SUMMARY="(dry run)"
347	else
348	    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
349	    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
350	    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
351	fi
352
353	END=$(date +%s)
354
355	# ==============================================================================================
356	# ━━━ Summary ━━━
357	# ==============================================================================================
358	if [[ "$REMAINDER_MODE" == true ]]; then
359	    echo "━━━━━ $ICON_SUMMARY DOCKER UPDATE (REMAINDER) SUMMARY ━━━━━"

            warn "DRY RUN — would rebuild $container from template"
            REBUILT+=("$container")
            continue
        fi
        log "$ICON_SYNC Rebuilding $container from template on new image..."
        if /usr/local/emhttp/plugins/dynamix.docker.manager/scripts/rebuild_container "$container" >/dev/null 2>&1; then
            log "$ICON_DONE $container rebuilt ✅"
            REBUILT+=("$container")
        else
            error "Failed to rebuild $container — will be picked up by docker_daily_restart.sh"
            notify "$container failed to rebuild after image update on $(hostname)" "Docker Update" "warning"
            REBUILD_FAILED+=("$container")
        fi
    done
fi

# ── Prune dangling images ─────────────────────────────────────────────────────
# Old images become dangling after a pull lands a new digest. Prune here so
# they don't accumulate across daily runs.
if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would prune dangling images"
    PRUNED_SUMMARY="(dry run)"
else
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi

END=$(date +%s)

# ==============================================================================================
# ━━━ Summary ━━━
# ==============================================================================================
if [[ "$REMAINDER_MODE" == true ]]; then
    echo "━━━━━ $ICON_SUMMARY DOCKER UPDATE (REMAINDER) SUMMARY ━━━━━"


The script already captures `OLD_ID` per container but throws it away after logging. I need to collect them and explicitly `docker rmi` after the rebuilds:


250	else
251	    echo "━━━ $ICON_CONTAINERS Docker Update — $(date '+%Y-%m-%d %H:%M:%S') ━━━"
252	    log "$ICON_CONTAINERS Containers: ${TARGET_CONTAINERS[*]}"
253	fi
254	echo ""
255
256	START=$(date +%s)
257	UPDATED=()
258	UP_TO_DATE=()
259	FAILED=()

else
    echo "━━━ $ICON_CONTAINERS Docker Update — $(date '+%Y-%m-%d %H:%M:%S') ━━━"
    log "$ICON_CONTAINERS Containers: ${TARGET_CONTAINERS[*]}"
fi
echo ""

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()


Edit

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()
OLD_IMAGE_IDS=()   # old image IDs to explicitly remove after rebuilds


The file /boot/config/plugins/varaverk/Docker_Essentials/docker_update.sh has been updated successfully. (file state is current in your context — no need to Read it back)

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()
OLD_IMAGE_IDS=()   # old image IDs to explicitly remove after rebuilds

+OLD_IMAGE_IDS=()   # old image IDs to explicitly remove after rebuilds

for container in "${TARGET_CONTAINERS[@]}"; do


        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
            UPDATED+=("$container")

        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
            UPDATED+=("$container")
            OLD_IMAGE_IDS+=("$OLD_ID")


        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
            UPDATED+=("$container")
            OLD_IMAGE_IDS+=("$OLD_ID")

log "$container — already up to date (${NEW_ID:7:12})"


Now replace the dangling-only prune with the targeted rmi + dangling fallback:


# ── Prune dangling images ─────────────────────────────────────────────────────
# Old images become dangling after a pull lands a new digest. Prune here so
# they don't accumulate across daily runs.
if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would prune dangling images"
    PRUNED_SUMMARY="(dry run)"
else
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi

# ── Remove old images ────────────────────────────────────────────────────────
# Explicitly rmi by the IDs captured before each pull. Tagged images are never
# caught by dangling-only prune, so this is the only reliable cleanup path.
# Fall through to dangling prune to catch any leftovers from other update paths.
if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would remove ${#OLD_IMAGE_IDS[@]} old image(s) and prune dangling"
    PRUNED_SUMMARY="(dry run)"
else
    for _old_id in "${OLD_IMAGE_IDS[@]}"; do
        docker rmi "$_old_id" >/dev/null 2>&1 || true
    done
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi


# ── Prune dangling images ─────────────────────────────────────────────────────
# Old images become dangling after a pull lands a new digest. Prune here so
# they don't accumulate across daily runs.
if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would prune dangling images"
    PRUNED_SUMMARY="(dry run)"
else
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi

# ── Remove old images ────────────────────────────────────────────────────────
# Explicitly rmi by the IDs captured before each pull. Tagged images are never
# caught by dangling-only prune, so this is the only reliable cleanup path.
# Fall through to dangling prune to catch any leftovers from other update paths.
if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would remove ${#OLD_IMAGE_IDS[@]} old image(s) and prune dangling"
    PRUNED_SUMMARY="(dry run)"
else
    for _old_id in "${OLD_IMAGE_IDS[@]}"; do
        docker rmi "$_old_id" >/dev/null 2>&1 || true
    done
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi

-# ── Prune dangling images ─────────────────────────────────────────────────────

-# Old images become dangling after a pull lands a new digest. Prune here so

-# they don't accumulate across daily runs.

+# ── Remove old images ────────────────────────────────────────────────────────

+# Explicitly rmi by the IDs captured before each pull. Tagged images are never

+# caught by dangling-only prune, so this is the only reliable cleanup path.

+# Fall through to dangling prune to catch any leftovers from other update paths.

-    warn "DRY RUN — would prune dangling images"

+    warn "DRY RUN — would remove ${#OLD_IMAGE_IDS[@]} old image(s) and prune dangling"

+    for _old_id in "${OLD_IMAGE_IDS[@]}"; do

+        docker rmi "$_old_id" >/dev/null 2>&1 || true


Now check if `docker_update_remaining.sh` has the same prune pattern and needs the same fix:


Bash

grep -n "prune\|OLD_ID\|UPDATED\|image.*rm" /boot/config/plugins/varaverk/Docker_Essentials/docker_update_remaining.sh | head -20

Check if docker_update_remaining has the same prune issue


10:# containers that received a new image, then prunes dangling images.
70:#     Pull all remaining running containers, restart those updated, prune images
166:UPDATED=()
185:        UPDATED+=("$container")
189:    OLD_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")
199:    NEW_ID=$(docker image inspect "$IMAGE" --format='{{.Id}}' 2>/dev/null || echo "")
202:        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
203:            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
204:            UPDATED+=("$container")
223:if [[ ${#UPDATED[@]} -gt 0 ]]; then
226:    log "$ICON_CONTAINERS Containers with new image: ${UPDATED[*]}"
228:    for container in "${UPDATED[@]}"; do
272:    warn "DRY RUN — would prune dangling images"
275:    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
290:if [[ ${#UPDATED[@]} -gt 0 ]]; then
291:    echo "$ICON_DONE       New image:   ${#UPDATED[@]}"
292:    log "  ${UPDATED[*]}"


Same pattern — same fix needed:


163	echo ""
164
165	START=$(date +%s)
166	UPDATED=()
167	UP_TO_DATE=()
168	FAILED=()
169
170	for container in "${REMAINING[@]}"; do
171	    [[ -z "$container" ]] && continue
172	    log "━━━ $ICON_CONTAINERS $container ━━━"

echo ""

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()

for container in "${REMAINING[@]}"; do
    [[ -z "$container" ]] && continue
    log "━━━ $ICON_CONTAINERS $container ━━━"


265	# ==============================================================================================
266	# ━━━ Prune Old Images ━━━
267	# ==============================================================================================
268	echo ""
269	echo "━━━ $ICON_SYNC Pruning Dangling Images — $(date '+%Y-%m-%d %H:%M:%S') ━━━"
270
271	if [[ "$DRY_RUN" == true ]]; then
272	    warn "DRY RUN — would prune dangling images"
273	    PRUNED_SUMMARY="(dry run)"
274	else
275	    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
276	    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
277	    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
278	fi
279
280	END=$(date +%s)
281
282	# ==============================================================================================
283	# ━━━ Summary ━━━
284	# ==============================================================================================

# ==============================================================================================
# ━━━ Prune Old Images ━━━
# ==============================================================================================
echo ""
echo "━━━ $ICON_SYNC Pruning Dangling Images — $(date '+%Y-%m-%d %H:%M:%S') ━━━"

if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would prune dangling images"
    PRUNED_SUMMARY="(dry run)"
else
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi

END=$(date +%s)

# ==============================================================================================
# ━━━ Summary ━━━
# ==============================================================================================


Edit

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()
OLD_IMAGE_IDS=()


The file /boot/config/plugins/varaverk/Docker_Essentials/docker_update_remaining.sh has been updated successfully. (file state is current in your context — no need to Read it back)

START=$(date +%s)
UPDATED=()
UP_TO_DATE=()
FAILED=()
OLD_IMAGE_IDS=()

UPDATED=()
UP_TO_DATE=()
FAILED=()
+OLD_IMAGE_IDS=()
for container in "${REMAINING[@]}"; do
[[ -z "$container" ]] && continue


        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
            UPDATED+=("$container")

        if [[ -n "$OLD_ID" ]] && [[ "$OLD_ID" != "$NEW_ID" ]]; then
            log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"
            UPDATED+=("$container")
            OLD_IMAGE_IDS+=("$OLD_ID")


log "$ICON_DONE  $container — updated ✅ (${OLD_ID:7:12} → ${NEW_ID:7:12})"

log "$container — already up to date (${NEW_ID:7:12})"


if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would prune dangling images"
    PRUNED_SUMMARY="(dry run)"
else
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi

if [[ "$DRY_RUN" == true ]]; then
    warn "DRY RUN — would remove ${#OLD_IMAGE_IDS[@]} old image(s) and prune dangling"
    PRUNED_SUMMARY="(dry run)"
else
    for _old_id in "${OLD_IMAGE_IDS[@]}"; do
        docker rmi "$_old_id" >/dev/null 2>&1 || true
    done
    PRUNED_OUTPUT=$(docker image prune -f 2>&1)
    [[ "$ENABLE_LOGGING" == "true" ]] && echo "$PRUNED_OUTPUT" | sed 's/^/  /'
    PRUNED_SUMMARY=$(echo "$PRUNED_OUTPUT" | grep -E "^Total reclaimed" || echo "nothing reclaimed")
fi