Introduces automatic creation of a self-documenting startup.json file on first startup, with example path configurations for Linux, Windows, and portable setups. Adds preset database configurations to database.xml for easy switching between SQLite and PostgreSQL. Refactors database config classes for XML serialization compatibility and ensures database.xml is never empty. Comprehensive documentation and migration guides included.
6.3 KiB
Fix: Empty database.xml on Startup
Problem
The database.xml file was being created empty on startup, causing Jellyfin to fail or not properly initialize the database configuration.
Root Cause
Issue 1: required Keyword Incompatibility
The DatabaseConfigurationOptions class had the DatabaseType property marked with the C# 11 required keyword:
public required string DatabaseType { get; set; }
Problem: The System.Xml.Serialization.XmlSerializer used by Jellyfin doesn't support the required keyword. When trying to serialize/deserialize:
- XML serializer couldn't create instances with required properties
- Serialization would fail silently or create empty files
- Deserialization from empty files would fail
Issue 2: Dictionary<string, T> Not XML-Serializable
The PresetConfigurations property used a Dictionary<string, PresetDatabaseConfiguration>:
public Dictionary<string, PresetDatabaseConfiguration>? PresetConfigurations { get; set; }
Problem: Dictionary<TKey, TValue> is not directly XML-serializable by XmlSerializer without custom serialization logic.
Solution Applied
Fix 1: Removed required Keyword
Changed DatabaseType to nullable and added default value in constructor:
Before:
public required string DatabaseType { get; set; }
After:
public DatabaseConfigurationOptions()
{
DatabaseType = "Jellyfin-SQLite";
LockingBehavior = DatabaseLockingBehaviorTypes.NoLock;
}
public string? DatabaseType { get; set; }
Fix 2: Replaced Dictionary with XML-Serializable List
Changed from Dictionary<string, T> to List<PresetConfigurationItem> with XML attributes:
Before:
public Dictionary<string, PresetDatabaseConfiguration>? PresetConfigurations { get; set; }
After:
[XmlArray("PresetConfigurations")]
[XmlArrayItem("PresetConfiguration")]
public List<PresetConfigurationItem>? PresetConfigurations { get; set; }
New supporting class:
public class PresetConfigurationItem
{
[XmlElement("key")]
public string? Key { get; set; }
[XmlElement("value")]
public PresetDatabaseConfiguration? Value { get; set; }
}
Fix 3: Added Null Check Safety
Added validation to ensure DatabaseType is never null when reading configuration:
// Ensure DatabaseType is set (handle corrupted or empty configuration files)
if (string.IsNullOrWhiteSpace(efCoreConfiguration.DatabaseType))
{
efCoreConfiguration.DatabaseType = "Jellyfin-SQLite";
configurationManager.SaveConfiguration("database", efCoreConfiguration);
}
Files Modified
-
src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs
- Removed
requiredkeyword - Added default constructor with defaults
- Changed
DictionarytoListwith XML attributes
- Removed
-
src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/PresetConfigurationItem.cs (NEW)
- Created new class for XML-serializable key-value pairs
- Added proper XML attributes
-
Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs
- Updated preset creation to use
List<PresetConfigurationItem> - Added null check for DatabaseType
- Updated preset creation to use
XML Output
The database.xml file now properly serializes:
<?xml version="1.0" encoding="utf-8"?>
<DatabaseConfigurationOptions>
<DatabaseType>Jellyfin-SQLite</DatabaseType>
<LockingBehavior>NoLock</LockingBehavior>
<PresetConfigurations>
<PresetConfiguration>
<key>SQLite</key>
<value>
<DatabaseType>Jellyfin-SQLite</DatabaseType>
<LockingBehavior>NoLock</LockingBehavior>
<Description>Default SQLite database configuration. Database stored in data directory.</Description>
</value>
</PresetConfiguration>
<PresetConfiguration>
<key>PostgreSQL-Local</key>
<value>
<DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
<LockingBehavior>NoLock</LockingBehavior>
<Description>PostgreSQL database on localhost. Update CustomProviderOptions with your database credentials.</Description>
</value>
</PresetConfiguration>
</PresetConfigurations>
</DatabaseConfigurationOptions>
Testing
- Delete existing database.xml (if any)
- Start Jellyfin
- Verify
database.xmlis created in config directory - Check file contains proper XML structure (not empty)
- Confirm Jellyfin uses SQLite by default
- Test switching to PostgreSQL by editing DatabaseType
Verification Commands
Windows (PowerShell)
# Check if file exists and has content
Get-Content "$env:LOCALAPPDATA\jellyfin\config\database.xml"
# Check file size (should be > 0 bytes)
(Get-Item "$env:LOCALAPPDATA\jellyfin\config\database.xml").Length
Linux
# Check if file exists and has content
cat ~/.config/jellyfin/database.xml
# Check file size
ls -lh ~/.config/jellyfin/database.xml
Expected Behavior
✅ database.xml created on first startup
✅ Contains proper XML with DatabaseType, LockingBehavior, and PresetConfigurations
✅ Defaults to SQLite if no configuration exists
✅ Can be edited to switch between databases
✅ Presets visible as templates in the file
Backward Compatibility
✅ Existing configurations will be loaded correctly
✅ Old database.xml files without presets will still work
✅ No data migration needed
✅ Graceful degradation - if file is corrupted, defaults to SQLite
Related Issues
This fix resolves:
- Empty database.xml files on startup
- Configuration not persisting
- Database provider selection not working
- Preset configurations not saving
Prevention
To prevent similar issues in future:
- ✅ Avoid using
requiredkeyword with XML-serialized classes - ✅ Use XML-serializable types (avoid Dictionary, use List instead)
- ✅ Add default constructors to serialized classes
- ✅ Test XML serialization/deserialization in unit tests
- ✅ Add null checks when reading configuration
See Also
- DATABASE_CONFIGURATION_GUIDE.md - How to configure database
- DATABASE_PRESETS_FEATURE.md - Preset configurations feature
- database.xml.example - Example configuration file