# 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:

```csharp
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>`:

```csharp
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:**
```csharp
public required string DatabaseType { get; set; }
```

**After:**
```csharp
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:**
```csharp
public Dictionary<string, PresetDatabaseConfiguration>? PresetConfigurations { get; set; }
```

**After:**
```csharp
[XmlArray("PresetConfigurations")]
[XmlArrayItem("PresetConfiguration")]
public List<PresetConfigurationItem>? PresetConfigurations { get; set; }
```

**New supporting class:**
```csharp
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:

```csharp
// 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

1. **src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/DatabaseConfigurationOptions.cs**
   - Removed `required` keyword
   - Added default constructor with defaults
   - Changed `Dictionary` to `List` with XML attributes

2. **src/Jellyfin.Database/Jellyfin.Database.Implementations/DbConfiguration/PresetConfigurationItem.cs** (NEW)
   - Created new class for XML-serializable key-value pairs
   - Added proper XML attributes

3. **Jellyfin.Server.Implementations/Extensions/ServiceCollectionExtensions.cs**
   - Updated preset creation to use `List<PresetConfigurationItem>`
   - Added null check for DatabaseType

## XML Output

The database.xml file now properly serializes:

```xml
<?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

1. **Delete existing database.xml** (if any)
2. **Start Jellyfin**
3. **Verify** `database.xml` is created in config directory
4. **Check** file contains proper XML structure (not empty)
5. **Confirm** Jellyfin uses SQLite by default
6. **Test switching** to PostgreSQL by editing DatabaseType

## Verification Commands

### Windows (PowerShell)
```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
```bash
# 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:
1. ✅ Avoid using `required` keyword with XML-serialized classes
2. ✅ Use XML-serializable types (avoid Dictionary, use List instead)
3. ✅ Add default constructors to serialized classes
4. ✅ Test XML serialization/deserialization in unit tests
5. ✅ Add null checks when reading configuration

## See Also

- [DATABASE_CONFIGURATION_GUIDE.md](DATABASE_CONFIGURATION_GUIDE.md) - How to configure database
- [DATABASE_PRESETS_FEATURE.md](DATABASE_PRESETS_FEATURE.md) - Preset configurations feature
- [database.xml.example](database.xml.example) - Example configuration file
