developer-tools

Is Lidarr Down? Real-Time Status & Outage Checker

Is Lidarr Down? Real-Time Status & Outage Checker

Lidarr is an open-source music collection manager and download automation tool with 3,500+ GitHub stars, built as part of the *arr suite and adapted specifically for music. It monitors for new album releases via Usenet and BitTorrent indexers, grabs releases automatically, and imports them to your music library with proper tagging sourced from MusicBrainz. Lidarr integrates with all major download clients (qBittorrent, SABnzbd, NZBGet, Deluge) and media servers (Plex, Navidrome, Beets), making it the standard tool for fully automated music library management. Home media server operators rely on Lidarr running continuously — when it goes down, new album grabs stop, imports stall, and your music library falls behind on releases.

Lidarr exposes a full REST API on port 8686. Monitoring both the process and the API health endpoint is the fastest way to detect failures before they result in a growing backlog of missing albums or stale artist metadata.

Quick Status Check

#!/bin/bash
# Lidarr health check
# Usage: LIDARR_API_KEY=your_key ./lidarr-check.sh

LIDARR_HOST="${LIDARR_HOST:-http://localhost:8686}"
LIDARR_API_KEY="${LIDARR_API_KEY:-your_api_key_here}"
PASS=0
FAIL=0

echo "=== Lidarr Health Check ==="
echo "Host: $LIDARR_HOST"
echo ""

# 1. Check process is running
if pgrep -x "Lidarr" > /dev/null 2>&1 || pgrep -f "Lidarr.exe" > /dev/null 2>&1; then
  echo "[OK]   Lidarr process is running"
  PASS=$((PASS+1))
else
  echo "[FAIL] Lidarr process not found"
  FAIL=$((FAIL+1))
fi

# 2. Check port 8686 is open
if nc -z localhost 8686 2>/dev/null; then
  echo "[OK]   Port 8686 is open"
  PASS=$((PASS+1))
else
  echo "[FAIL] Port 8686 is not reachable"
  FAIL=$((FAIL+1))
fi

# 3. Check system status API
STATUS=$(curl -sf --max-time 10 \
  -H "X-Api-Key: $LIDARR_API_KEY" \
  "$LIDARR_HOST/api/v1/system/status")
if [ $? -eq 0 ]; then
  VERSION=$(echo "$STATUS" | grep -o '"version":"[^"]*"' | cut -d'"' -f4)
  echo "[OK]   API responding — Lidarr v$VERSION"
  PASS=$((PASS+1))
else
  echo "[FAIL] /api/v1/system/status did not respond"
  FAIL=$((FAIL+1))
fi

# 4. Check health endpoint for WARNING/ERROR items
HEALTH=$(curl -sf --max-time 10 \
  -H "X-Api-Key: $LIDARR_API_KEY" \
  "$LIDARR_HOST/api/v1/health")
if [ $? -eq 0 ]; then
  ISSUE_COUNT=$(echo "$HEALTH" | grep -o '"type":"' | wc -l | tr -d ' ')
  if [ "$ISSUE_COUNT" -eq 0 ]; then
    echo "[OK]   Health check clean — no issues reported"
  else
    echo "[WARN] Health check returned $ISSUE_COUNT issue(s):"
    echo "$HEALTH" | grep -o '"message":"[^"]*"' | cut -d'"' -f4 | while read -r msg; do
      echo "       - $msg"
    done
  fi
  PASS=$((PASS+1))
else
  echo "[FAIL] /api/v1/health did not respond"
  FAIL=$((FAIL+1))
fi

echo ""
echo "=== Result: $PASS passed, $FAIL failed ==="
[ "$FAIL" -eq 0 ] && exit 0 || exit 1

Python Health Check

#!/usr/bin/env python3
"""
Lidarr health check
Checks system status, health issues, download queue, missing albums, artist count, and album count.
"""

import os
import sys
import json
import urllib.request
import urllib.error

LIDARR_HOST = os.environ.get("LIDARR_HOST", "http://localhost:8686")
LIDARR_API_KEY = os.environ.get("LIDARR_API_KEY", "your_api_key_here")

HEADERS = {
    "X-Api-Key": LIDARR_API_KEY,
    "Accept": "application/json",
}

results = []
failures = 0


def check(label, ok, detail=""):
    global failures
    status = "OK  " if ok else "FAIL"
    if not ok:
        failures += 1
    msg = f"[{status}] {label}"
    if detail:
        msg += f" — {detail}"
    results.append(msg)
    print(msg)


def api_get(path, timeout=10):
    url = f"{LIDARR_HOST}{path}"
    req = urllib.request.Request(url, headers=HEADERS)
    try:
        with urllib.request.urlopen(req, timeout=timeout) as resp:
            return json.loads(resp.read().decode())
    except urllib.error.HTTPError as e:
        raise RuntimeError(f"HTTP {e.code} from {path}")
    except Exception as e:
        raise RuntimeError(f"Request failed: {e}")


print("=== Lidarr Python Health Check ===")
print(f"Host: {LIDARR_HOST}\n")

# 1. System status — version and OS
try:
    status = api_get("/api/v1/system/status")
    version = status.get("version", "unknown")
    branch = status.get("branch", "unknown")
    os_name = status.get("osName", "unknown")
    check("System status API", True, f"v{version} ({branch}) on {os_name}")
except RuntimeError as e:
    check("System status API", False, str(e))

# 2. Health endpoint — list any WARNING or ERROR items
try:
    health = api_get("/api/v1/health")
    issues = [h for h in health if h.get("type") in ("warning", "error")]
    if not issues:
        check("Health endpoint", True, "no issues reported")
    else:
        check("Health endpoint", False, f"{len(issues)} issue(s) found")
        for issue in issues:
            print(f"       [{issue.get('type','?').upper()}] {issue.get('message','')}")
except RuntimeError as e:
    check("Health endpoint", False, str(e))

# 3. Download queue — count of active items
try:
    queue = api_get("/api/v1/queue")
    total = queue.get("totalRecords", 0)
    check("Download queue", True, f"{total} item(s) in queue")
except RuntimeError as e:
    check("Download queue", False, str(e))

# 4. Wanted missing — albums Lidarr hasn't been able to grab
try:
    missing = api_get("/api/v1/wanted/missing?pageSize=1")
    total_missing = missing.get("totalRecords", 0)
    ok = total_missing < 200
    check(
        "Wanted/missing albums",
        ok,
        f"{total_missing} missing album(s)"
        + ("" if ok else " — unusually high, check indexers"),
    )
except RuntimeError as e:
    check("Wanted/missing albums", False, str(e))

# 5. Artist count — confirms database is accessible and populated
try:
    artists = api_get("/api/v1/artist")
    count = len(artists) if isinstance(artists, list) else 0
    check("Artist library", True, f"{count} artist(s) tracked")
except RuntimeError as e:
    check("Artist library", False, str(e))

# 6. Album count — confirms album metadata was loaded from MusicBrainz
try:
    albums = api_get("/api/v1/album?includeAllArtistAlbums=false&pageSize=1")
    # Response may be a list or a paged object depending on Lidarr version
    if isinstance(albums, list):
        count = len(albums)
    elif isinstance(albums, dict):
        count = albums.get("totalRecords", len(albums.get("records", [])))
    else:
        count = 0
    check("Album library", True, f"{count} album(s) indexed")
except RuntimeError as e:
    check("Album library", False, str(e))

# Summary
print(f"\n=== Result: {len(results) - failures} passed, {failures} failed ===")
sys.exit(0 if failures == 0 else 1)

Common Lidarr Outage Causes

SymptomLikely CauseResolution
Album metadata fails to load or shows blank MusicBrainz connectivity issue — metadata source unreachable Check network connectivity to musicbrainz.org; restart Lidarr; re-trigger artist refresh
Albums searched but never download Download client disconnected or credentials changed Settings → Download Clients → test connection; re-enter password if rotated
Indexer searches return zero music results Indexer misconfigured for music categories or API key expired Settings → Indexers → test each indexer; verify music-specific categories are enabled
Lidarr crashes on startup SQLite database corruption after unclean shutdown Stop Lidarr; run sqlite3 lidarr.db "PRAGMA integrity_check"; restore from backup
Completed downloads not importing to music library Disk full — import path has no free space Free disk space on the target drive; check df -h; adjust import path if needed
Duplicate artist entries with mismatched metadata Artist name variation causing MusicBrainz ID mismatch Merge duplicate artists in Lidarr UI; set canonical MusicBrainz ID manually on artist page

Architecture Overview

ComponentFunctionFailure Impact
Lidarr Core (C#/.NET) Main process — scheduling, API, import logic Total failure; all grabs and imports stop
SQLite Database Stores artists, albums, tracks, history, and quality profiles Crash on startup; music library tracking lost if corrupted
MusicBrainz Metadata Agent Fetches artist and album metadata for tagging and matching Blank metadata; new artists fail to populate; album art missing
Indexer RSS Engine Polls Usenet/torrent indexers for new album release announcements No new grabs; existing downloads unaffected
Download Client Integration Sends NZB/torrent to qBittorrent, SABnzbd, etc. Albums found but never sent to downloader
Import/Tag Engine Moves completed downloads into library with MusicBrainz-correct tags Downloads complete but files untagged and not visible in Plex/Navidrome

Uptime History

DateIncident TypeDurationImpact
2026-02 MusicBrainz API rate limiting ~4 hrs Artist metadata lookups failed; new album imports stalled with blank tags
2025-11 SQLite corruption after unclean shutdown ~2 hrs (restore from backup) Lidarr offline; artist and album tracking lost until database restored
2025-09 Download client credential rotation ~18 hrs undetected All album grabs queued internally but never sent to download client
2025-07 Disk full on music library drive ~3 hrs Completed downloads not imported; import errors logged silently

Monitor Lidarr Automatically

Lidarr failures are silent by default — the process may be running while the download client connection is broken, MusicBrainz metadata is timing out, or disk space is exhausted, with no visible alert. ezmon.com monitors your Lidarr endpoints from multiple external probes and alerts your team via Slack, PagerDuty, or SMS the moment the API stops responding or health checks report critical errors.

Set up Lidarr monitoring free at ezmon.com →

lidarrmusic-managementhome-serverself-hostedmusic-downloadsstatus-checker