Files
pgsql-jellyfin/docs/POSTGRESQL_TROUBLESHOOTING.md
T
wjones a3eb4b1b57 Add automatic PostgreSQL database creation and migration
- Added Jellyfin.Database.Providers.Postgres project with full EF Core migration support for PostgreSQL.
- Implemented automatic database creation and privilege assignment on startup.
- Generated initial migration and model snapshot for PostgreSQL schema.
- Updated build, test, and dependency files to include PostgreSQL provider and Npgsql packages.
- Added PowerShell script for generating and testing PostgreSQL migrations.
- No changes to application logic outside database provider/migration infrastructure.
2026-02-22 18:51:24 -05:00

7.6 KiB

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

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:

<LockingBehavior>NoLock</LockingBehavior>

Complete PostgreSQL Configuration:

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

    # Linux/macOS
    systemctl status postgresql
    
    # Windows (PowerShell)
    Get-Service -Name postgresql*
    
  2. Test connection manually:

    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:

    # Linux/macOS
    sudo systemctl restart postgresql
    
    # Windows
    Restart-Service postgresql*
    

Error: "Password authentication failed"

  1. Reset the password:

    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:

    psql --version
    

    Minimum required: PostgreSQL 12

  2. Verify database exists and is accessible:

    psql -h localhost -U jellyfin -d jellyfin -c "SELECT version();"
    
  3. Check database user permissions:

    -- Connect as postgres superuser
    GRANT ALL PRIVILEGES ON DATABASE jellyfin TO jellyfin;
    GRANT ALL PRIVILEGES ON SCHEMA public TO jellyfin;
    
  4. Enable detailed logging:

    <CustomDatabaseOption>
      <Key>EnableSensitiveDataLogging</Key>
      <Value>True</Value>
    </CustomDatabaseOption>
    

Performance Issues

Slow Queries

  1. Enable Connection Pooling (should be default):

    <CustomDatabaseOption>
      <Key>pooling</Key>
      <Value>True</Value>
    </CustomDatabaseOption>
    
  2. Increase Command Timeout for large libraries:

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

    -- Check existing indexes
    SELECT * FROM pg_indexes WHERE schemaname = 'public';
    

High Memory Usage

PostgreSQL connection pooling maintains connections. To reduce:

<CustomDatabaseOption>
  <Key>pooling</Key>
  <Value>False</Value>
</CustomDatabaseOption>

⚠️ Warning: Disabling pooling will impact performance.

Debugging

Enable Detailed SQL Logging

Add to config/database.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:

<LockingBehavior>Pessimistic</LockingBehavior>

Use instead:

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

<Value>postgresql://localhost:5432</Value>

Correct:

<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

    cp config/database.xml config/database.xml.backup
    
  3. Switch Back to SQLite (temporary):

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