# SQLite Migration Filtering Fix ## Problem When running Jellyfin with PostgreSQL, the startup was failing with an error: ``` [ERR] Main: Cannot make a backup of "library.db" at path "/var/lib/jellyfin/data/library.db" because file could not be found at "/var/lib/jellyfin/data" ``` This occurred even though: 1. The migration system was using PostgreSQL (not SQLite) 2. SQLite-specific migrations were marked with `RequiresSqlite = true` 3. SQLite migrations were supposed to be skipped ## Root Cause The issue was in the **backup preparation phase** of the migration system (`JellyfinMigrationService.cs`). ### What Was Happening 1. **Migration Execution** - SQLite-specific migrations were correctly filtered out (lines 222-233) - ✅ This worked correctly 2. **Backup Preparation** - ALL migrations were included when determining backup requirements (line 400-404) - ❌ This included SQLite-specific migrations - ❌ Their backup requirements were aggregated even though the migrations wouldn't run - ❌ System tried to backup `library.db` that doesn't exist in PostgreSQL setup ### Code Flow ```csharp // Line 400-404 - BEFORE FIX backupInstruction = Migrations.SelectMany(e => e) .Where(e => appliedMigrations.All(f => f.MigrationId != e.BuildCodeMigrationId())) .Select(e => e.BackupRequirements) // ← Includes SQLite migration requirements! .Where(e => e is not null) .Aggregate(backupInstruction, MergeBackupAttributes!); // Line 406 - Then tries to backup based on aggregated requirements if (backupInstruction.LegacyLibraryDb) // ← True because SQLite migration requested it { // Tries to backup library.db even though we're using PostgreSQL! var libraryDbPath = Path.Combine(_applicationPaths.DataPath, DbFilename); if (File.Exists(libraryDbPath)) // ← File doesn't exist → ERROR ``` ## Solution Added filtering to skip SQLite-specific migrations when aggregating backup requirements: ```csharp // Filter out SQLite-specific migrations when determining backup requirements bool isSqliteProvider = false; // SQLite is no longer supported as runtime provider backupInstruction = Migrations.SelectMany(e => e) .Where(e => appliedMigrations.All(f => f.MigrationId != e.BuildCodeMigrationId())) .Where(e => isSqliteProvider || !e.Metadata.RequiresSqlite) // ← NEW: Skip SQLite migrations .Select(e => e.BackupRequirements) .Where(e => e is not null) .Aggregate(backupInstruction, MergeBackupAttributes!); ``` ### What This Fixes 1. ✅ SQLite-specific migrations are filtered out BEFORE aggregating backup requirements 2. ✅ System no longer tries to backup `library.db` when using PostgreSQL 3. ✅ Startup completes successfully without SQLite file errors 4. ✅ Maintains compatibility if SQLite provider is ever re-enabled (checks `isSqliteProvider`) ## Impact ### Before Fix - ❌ Jellyfin startup failed when using PostgreSQL - ❌ Error: "Cannot make a backup of library.db" - ❌ Migration system tried to backup non-existent SQLite files ### After Fix - ✅ Jellyfin starts successfully with PostgreSQL - ✅ SQLite-specific migrations are completely skipped (both execution AND backup) - ✅ Only relevant migrations run and their files are backed up ## Testing To verify the fix works: 1. **Start Jellyfin with PostgreSQL** - Should complete startup without errors 2. **Check logs** - Should see: ``` [INF] Skipping X SQLite-specific migrations because current provider is not SQLite ``` 3. **No backup errors** - Should NOT see: ``` [ERR] Cannot make a backup of "library.db" ``` ## Related Files - **`Jellyfin.Server/Migrations/JellyfinMigrationService.cs`** (Line 400-407) - Modified to filter SQLite migrations before aggregating backup requirements - **`Jellyfin.Server/Migrations/Routines/ReseedFolderFlag.cs`** - Example SQLite-specific migration with `RequiresSqlite = true` - Has `JellyfinMigrationBackupAttribute(JellyfinDb = true)` which was causing backup attempt ## Migration Attributes ### RequiresSqlite ```csharp [JellyfinMigration("2025-07-30T21:50:00", nameof(ReseedFolderFlag), RequiresSqlite = true)] public class ReseedFolderFlag : IAsyncMigrationRoutine ``` **Purpose:** Marks migrations that require SQLite's `library.db` file **Usage:** Set to `true` for legacy migrations that: - Read from old SQLite `library.db.old` files - Require SQLite-specific features - Should only run when SQLite is the active database provider ### Backup Filtering The fix ensures that `RequiresSqlite` is respected in TWO places: 1. **Migration Execution** (already working) ```csharp migrationStage = migrationStage.Where(m => !m.Metadata.RequiresSqlite).ToList(); ``` 2. **Backup Preparation** (NOW FIXED) ```csharp .Where(e => isSqliteProvider || !e.Metadata.RequiresSqlite) ``` ## Background: SQLite Removal Jellyfin is migrating away from SQLite to support multiple database providers (PostgreSQL, SQL Server, etc.): 1. **Runtime Support** - SQLite is no longer a supported runtime database provider 2. **Migration Support** - SQLite migration code remains for users upgrading from old versions 3. **Legacy File Support** - Some migrations read old `library.db` files to migrate data 4. **Flag Value** - `isSqliteProvider` is hardcoded to `false` (line 224) This fix ensures the migration system properly handles this transition state where: - SQLite migrations exist for backward compatibility - But the runtime only supports PostgreSQL/SQL Server - Backup system shouldn't try to backup files that don't exist ## Future Considerations If SQLite runtime support is ever re-added: 1. Set `isSqliteProvider = true` based on actual database provider 2. SQLite migrations will run again 3. `library.db` backups will be attempted (and should exist) The current implementation is ready for this - it just needs the provider detection logic updated.