Previously, the migration system would attempt to back up the legacy SQLite library.db file even when running with non-SQLite providers (e.g., PostgreSQL), causing startup errors. This was due to SQLite-specific migrations not being filtered out during backup requirement aggregation. This commit adds filtering to exclude migrations marked as RequiresSqlite from backup processing unless the provider is actually SQLite (currently unsupported). This prevents erroneous backup attempts and ensures only relevant migrations and backups are processed. Documentation has been updated to explain the issue and solution.
5.8 KiB
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:
- The migration system was using PostgreSQL (not SQLite)
- SQLite-specific migrations were marked with
RequiresSqlite = true - 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
-
Migration Execution - SQLite-specific migrations were correctly filtered out (lines 222-233)
- ✅ This worked correctly
-
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.dbthat doesn't exist in PostgreSQL setup
Code Flow
// 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:
// 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
- ✅ SQLite-specific migrations are filtered out BEFORE aggregating backup requirements
- ✅ System no longer tries to backup
library.dbwhen using PostgreSQL - ✅ Startup completes successfully without SQLite file errors
- ✅ 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:
- Start Jellyfin with PostgreSQL - Should complete startup without errors
- Check logs - Should see:
[INF] Skipping X SQLite-specific migrations because current provider is not SQLite - 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
- Example SQLite-specific migration with
Migration Attributes
RequiresSqlite
[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.oldfiles - 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:
-
Migration Execution (already working)
migrationStage = migrationStage.Where(m => !m.Metadata.RequiresSqlite).ToList(); -
Backup Preparation (NOW FIXED)
.Where(e => isSqliteProvider || !e.Metadata.RequiresSqlite)
Background: SQLite Removal
Jellyfin is migrating away from SQLite to support multiple database providers (PostgreSQL, SQL Server, etc.):
- Runtime Support - SQLite is no longer a supported runtime database provider
- Migration Support - SQLite migration code remains for users upgrading from old versions
- Legacy File Support - Some migrations read old
library.dbfiles to migrate data - Flag Value -
isSqliteProvideris hardcoded tofalse(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:
- Set
isSqliteProvider = truebased on actual database provider - SQLite migrations will run again
library.dbbackups will be attempted (and should exist)
The current implementation is ready for this - it just needs the provider detection logic updated.