# PostgreSQL Troubleshooting Guide

This guide helps resolve common issues when using PostgreSQL with Jellyfin.

## SynchronizationLockException Error

### Error Message
```
System.Threading.SynchronizationLockException: The write lock is being released without being held.
```

### Cause
This error occurs when using `Pessimistic` locking behavior with PostgreSQL. The issue stems from:
- EF Core interceptors executing on different threads during async operations
- `ReaderWriterLockSlim.IsWriteLockHeld` being thread-local, not async-context-aware
- Transaction and command interceptors both trying to acquire locks

### Solution 1: Use NoLock Behavior (Recommended)
PostgreSQL has built-in MVCC (Multi-Version Concurrency Control) and transaction isolation, making application-level pessimistic locking unnecessary and potentially problematic.

**Update your `config/database.xml`:**
```xml
<LockingBehavior>NoLock</LockingBehavior>
```

**Complete PostgreSQL Configuration:**
```xml
<?xml version="1.0" encoding="utf-8"?>
<DatabaseConfigurationOptions>
  <DatabaseType>Jellyfin-PostgreSQL</DatabaseType>
  <LockingBehavior>NoLock</LockingBehavior>
  <CustomProviderOptions>
    <Options>
      <CustomDatabaseOption>
        <Key>host</Key>
        <Value>localhost</Value>
      </CustomDatabaseOption>
      <CustomDatabaseOption>
        <Key>database</Key>
        <Value>jellyfin</Value>
      </CustomDatabaseOption>
      <CustomDatabaseOption>
        <Key>username</Key>
        <Value>jellyfin</Value>
      </CustomDatabaseOption>
      <CustomDatabaseOption>
        <Key>password</Key>
        <Value>your_password</Value>
      </CustomDatabaseOption>
    </Options>
  </CustomProviderOptions>
</DatabaseConfigurationOptions>
```

### Solution 2: Fixed Pessimistic Locking (If Needed)
The pessimistic locking implementation has been updated to use `AsyncLocal<int>` for tracking lock depth across async operations. However, this is **not recommended** for PostgreSQL as it adds unnecessary overhead.

If you must use pessimistic locking:
1. Ensure you have the latest code with the `AsyncLocal` fix
2. Use with caution as it may impact performance
3. Monitor for deadlocks in application logs

## Connection Issues

### Error: "Could not connect to server"

**Checks:**
1. Verify PostgreSQL is running:
   ```bash
   # Linux/macOS
   systemctl status postgresql
   
   # Windows (PowerShell)
   Get-Service -Name postgresql*
   ```

2. Test connection manually:
   ```bash
   psql -h localhost -U jellyfin -d jellyfin
   ```

3. Check `pg_hba.conf` authentication settings:
   ```
   # Allow local connections
   host    jellyfin    jellyfin    127.0.0.1/32    md5
   host    jellyfin    jellyfin    ::1/128         md5
   ```

4. Restart PostgreSQL after changing configuration:
   ```bash
   # Linux/macOS
   sudo systemctl restart postgresql
   
   # Windows
   Restart-Service postgresql*
   ```

### Error: "Password authentication failed"

1. Reset the password:
   ```sql
   ALTER USER jellyfin WITH PASSWORD 'new_secure_password';
   ```

2. Update `database.xml` with the new password

3. Ensure password doesn't contain XML special characters (`<`, `>`, `&`, `'`, `"`). If it does, use XML encoding:
   - `<` → `&lt;`
   - `>` → `&gt;`
   - `&` → `&amp;`
   - `'` → `&apos;`
   - `"` → `&quot;`

## Migration Issues

### Error: "Database migration failed"

1. Check PostgreSQL version:
   ```bash
   psql --version
   ```
   Minimum required: PostgreSQL 12

2. Verify database exists and is accessible:
   ```bash
   psql -h localhost -U jellyfin -d jellyfin -c "SELECT version();"
   ```

3. Check database user permissions:
   ```sql
   -- Connect as postgres superuser
   GRANT ALL PRIVILEGES ON DATABASE jellyfin TO jellyfin;
   GRANT ALL PRIVILEGES ON SCHEMA public TO jellyfin;
   ```

4. Enable detailed logging:
   ```xml
   <CustomDatabaseOption>
     <Key>EnableSensitiveDataLogging</Key>
     <Value>True</Value>
   </CustomDatabaseOption>
   ```

## Performance Issues

### Slow Queries

1. **Enable Connection Pooling** (should be default):
   ```xml
   <CustomDatabaseOption>
     <Key>pooling</Key>
     <Value>True</Value>
   </CustomDatabaseOption>
   ```

2. **Increase Command Timeout** for large libraries:
   ```xml
   <CustomDatabaseOption>
     <Key>command-timeout</Key>
     <Value>60</Value>
   </CustomDatabaseOption>
   ```

3. **Optimize PostgreSQL** configuration in `postgresql.conf`:
   ```
   shared_buffers = 256MB          # 25% of RAM for dedicated server
   effective_cache_size = 1GB      # 50-75% of RAM
   maintenance_work_mem = 64MB
   checkpoint_completion_target = 0.9
   wal_buffers = 16MB
   default_statistics_target = 100
   random_page_cost = 1.1          # For SSD storage
   effective_io_concurrency = 200  # For SSD storage
   work_mem = 4MB
   ```

4. **Create Indexes** for common queries (EF Core migrations should handle this, but verify):
   ```sql
   -- Check existing indexes
   SELECT * FROM pg_indexes WHERE schemaname = 'public';
   ```

### High Memory Usage

PostgreSQL connection pooling maintains connections. To reduce:
```xml
<CustomDatabaseOption>
  <Key>pooling</Key>
  <Value>False</Value>
</CustomDatabaseOption>
```

⚠️ **Warning**: Disabling pooling will impact performance.

## Debugging

### Enable Detailed SQL Logging

Add to `config/database.xml`:
```xml
<CustomDatabaseOption>
  <Key>EnableSensitiveDataLogging</Key>
  <Value>True</Value>
</CustomDatabaseOption>
```

⚠️ **Security Warning**: This logs SQL queries including parameter values. Only use for debugging and disable in production.

### Check Jellyfin Logs

Logs are located at:
- Linux: `/var/log/jellyfin/`
- Windows: `%PROGRAMDATA%\Jellyfin\Server\log\`
- Docker: `/config/log/`

Look for lines containing:
- `PostgreSQL connection:`
- `The database locking mode has been set to:`
- Database errors in the startup sequence

### Monitor PostgreSQL Logs

Enable query logging in `postgresql.conf`:
```
log_statement = 'all'              # Log all queries (very verbose)
log_min_duration_statement = 1000  # Log queries taking > 1 second
```

Then check PostgreSQL logs:
- Linux: `/var/log/postgresql/`
- Windows: `%PROGRAMDATA%\PostgreSQL\<version>\data\log\`

## Common Configuration Mistakes

### 1. Wrong Locking Behavior
❌ **Don't use:**
```xml
<LockingBehavior>Pessimistic</LockingBehavior>
```

✅ **Use instead:**
```xml
<LockingBehavior>NoLock</LockingBehavior>
```

### 2. Missing CustomProviderOptions
PostgreSQL requires `CustomProviderOptions` even though it's now a built-in provider (for backward compatibility).

### 3. Incorrect Port Format
❌ **Wrong:**
```xml
<Value>postgresql://localhost:5432</Value>
```

✅ **Correct:**
```xml
<CustomDatabaseOption>
  <Key>host</Key>
  <Value>localhost</Value>
</CustomDatabaseOption>
<CustomDatabaseOption>
  <Key>port</Key>
  <Value>5432</Value>
</CustomDatabaseOption>
```

## Recovery Steps

If Jellyfin won't start due to database issues:

1. **Stop Jellyfin**

2. **Backup Current Configuration**
   ```bash
   cp config/database.xml config/database.xml.backup
   ```

3. **Switch Back to SQLite** (temporary):
   ```xml
   <?xml version="1.0" encoding="utf-8"?>
   <DatabaseConfigurationOptions>
     <DatabaseType>Jellyfin-SQLite</DatabaseType>
     <LockingBehavior>NoLock</LockingBehavior>
   </DatabaseConfigurationOptions>
   ```

4. **Restart Jellyfin** and verify it works

5. **Fix PostgreSQL configuration** and try again

## Getting Help

If you're still experiencing issues:

1. Enable detailed logging (see Debugging section above)
2. Collect logs from both Jellyfin and PostgreSQL
3. Note your configuration (without password)
4. Check Jellyfin forums/GitHub issues with:
   - Error messages
   - PostgreSQL version
   - Jellyfin version
   - Operating system
