#!/usr/bin/env bash # Direct SQLite fix for Jellyfin 10.10.3 home-screen sections. # # Why this exists: # The REST endpoint `POST /DisplayPreferences/usersettings?client=Jellyfin Web` # updates `DisplayPreferences.CustomPrefs` but does NOT insert into the # `HomeSection` table for that client (it only inserts when called with # client="emby"). The web client reads from `HomeSection` rows on the # `Jellyfin Web` DisplayPreferences row, so the legacy POST has no # visible effect until those rows exist. # # What this script does (idempotent): # 1. Insert a `Jellyfin Web` DisplayPreferences row for any user missing one. # 2. Seed canonical home layout [Resume, LatestMedia, None*8] for every # DisplayPreferences row that has zero HomeSection rows. # 3. Replace any Type=7 (NextUp) with Type=0 (None) across the table. # # Type integers (Jellyfin.Data.Enums.HomeSectionType): # 0=None, 1=SmallLibraryTiles, 2=LibraryButtons, 3=ActiveRecordings, # 4=Resume, 5=ResumeAudio, 6=LatestMedia, 7=NextUp, 8=LiveTv, 9=ResumeBook # # Container must be stopped during write to avoid corrupting the EF Core # WAL. After write, restart the container. # # Usage: # docker stop jellyfin # DB=/home/docker/jellyfin/config/data/jellyfin.db bin/fix-home-db.sh # docker start jellyfin set -euo pipefail DB="${DB:-/home/docker/jellyfin/config/data/jellyfin.db}" [ -f "$DB" ] || { echo "DB not found at $DB"; exit 1; } cp -n "$DB" "$DB.bak.$(date +%s)" sqlite3 "$DB" <<'SQL' .bail on BEGIN; -- 1) Create Jellyfin Web DP row for users missing one. INSERT INTO DisplayPreferences (UserId, Client, ShowSidebar, ShowBackdrop, ScrollDirection, SkipForwardLength, SkipBackwardLength, ChromecastVersion, EnableNextVideoInfoOverlay, ItemId) SELECT u.Id, 'Jellyfin Web', 0, 1, 0, 30000, 10000, 0, 0, '00000000-0000-0000-0000-000000000000' FROM Users u WHERE NOT EXISTS ( SELECT 1 FROM DisplayPreferences d WHERE UPPER(d.UserId) = UPPER(u.Id) AND d.Client = 'Jellyfin Web' ); -- 2) For any DP with zero HomeSection rows, seed [Resume, LatestMedia, None*8]. INSERT INTO HomeSection (DisplayPreferencesId, "Order", Type) SELECT d.Id, 0, 4 FROM DisplayPreferences d WHERE NOT EXISTS (SELECT 1 FROM HomeSection h WHERE h.DisplayPreferencesId=d.Id); INSERT INTO HomeSection (DisplayPreferencesId, "Order", Type) SELECT d.Id, 1, 6 FROM DisplayPreferences d WHERE (SELECT COUNT(*) FROM HomeSection h WHERE h.DisplayPreferencesId=d.Id) = 1; INSERT INTO HomeSection (DisplayPreferencesId, "Order", Type) SELECT d.Id, ord, 0 FROM DisplayPreferences d CROSS JOIN (SELECT 2 AS ord UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) WHERE (SELECT COUNT(*) FROM HomeSection h WHERE h.DisplayPreferencesId=d.Id) = 2; -- 3) Replace NextUp (7) with None (0) across all DPs. UPDATE HomeSection SET Type = 0 WHERE Type = 7; COMMIT; SQL echo "[+] $DB normalized" echo "=== type summary ===" sqlite3 "$DB" "SELECT Type, COUNT(*) FROM HomeSection GROUP BY Type"