Skip to content

[BUG] Login succeeds but frontend stays on “Redirecting” and dashboard route renders blank/404 #562

Description

@vleeuwenmenno

Describe the bug
A valid login succeeds according to the API, but the UI never leaves the login screen. After submitting valid credentials, the login form shows "Success / Login successful! Redirecting..." and then stays there.

If I manually open /web/dashboard/, the page is blank/white.

The backend accepts the login request (POST /api/v1/auth/cookie/login returns 204) and immediately after that /api/v1/users/me can return 200, but frontend routes like /web/ and /web/dashboard/ are served with HTTP 404. Later dashboard API calls begin returning 401, and the UI appears stuck or blank.

To Reproduce
Steps to reproduce the behavior:

  1. Deploy MediaManager v1.12.3 with Docker Compose.
  2. Start with a Postgres-backed MediaManager setup and a default/admin user.
  3. Go to http://server-ip:8000/web/login.
  4. Log in with valid credentials.
  5. See "Success / Login successful! Redirecting..." remain on the login screen.
  6. Manually open http://server-ip:8000/web/dashboard/.
  7. See a blank/white page.

Expected behavior
After a successful login, the browser should navigate to the dashboard and render the dashboard UI.

Directly opening /web/dashboard/ should also load the SPA route successfully.

Screenshots
Login page: (No redirect happens!)
Image
After manually navigating to the dashboard page:
Image

Server Logs
Relevant excerpts:

mediamanager | POST /api/v1/auth/cookie/login HTTP/1.1" 204
mediamanager | GET /api/v1/users/me HTTP/1.1" 200
mediamanager | GET /web/dashboard/ HTTP/1.1" 404
mediamanager | GET /web/_app/version.json HTTP/1.1" 304
mediamanager | GET /api/v1/users/me HTTP/1.1" 401
mediamanager | POST /api/v1/auth/cookie/logout HTTP/1.1" 401
mediamanager | GET /api/v1/tv/shows HTTP/1.1" 401
mediamanager | GET /api/v1/movies HTTP/1.1" 401

On startup, Postgres also logs repeated scheduler duplicate key errors:

mediamanager-postgres | ERROR: duplicate key value violates unique constraint "apscheduler_jobs_pkey"
mediamanager-postgres | DETAIL: Key (id)=(import_all_movie_torrents) already exists.
mediamanager-postgres | STATEMENT: INSERT INTO apscheduler_jobs (id, next_run_time, job_state) VALUES ($1::VARCHAR, $2, $3)

mediamanager-postgres | ERROR: duplicate key value violates unique constraint "apscheduler_jobs_pkey"
mediamanager-postgres | DETAIL: Key (id)=(import_all_show_torrents) already exists.
mediamanager-postgres | STATEMENT: INSERT INTO apscheduler_jobs (id, next_run_time, job_state) VALUES ($1::VARCHAR, $2, $3)

mediamanager-postgres | ERROR: duplicate key value violates unique constraint "apscheduler_jobs_pkey"
mediamanager-postgres | DETAIL: Key (id)=(auto_download_all_approved_season_requests) already exists.
mediamanager-postgres | STATEMENT: INSERT INTO apscheduler_jobs (id, next_run_time, job_state) VALUES ($1::VARCHAR, $2, $3)

mediamanager-postgres | ERROR: duplicate key value violates unique constraint "apscheduler_jobs_pkey"
mediamanager-postgres | DETAIL: Key (id)=(auto_download_all_approved_movie_requests) already exists.
mediamanager-postgres | STATEMENT: INSERT INTO apscheduler_jobs (id, next_run_time, job_state) VALUES ($1::VARCHAR, $2, $3)

mediamanager-postgres | ERROR: duplicate key value violates unique constraint "apscheduler_jobs_pkey"
mediamanager-postgres | DETAIL: Key (id)=(update_all_movies_metadata) already exists.
mediamanager-postgres | STATEMENT: INSERT INTO apscheduler_jobs (id, next_run_time, job_state) VALUES ($1::VARCHAR, $2, $3)

mediamanager-postgres | ERROR: duplicate key value violates unique constraint "apscheduler_jobs_pkey"
mediamanager-postgres | DETAIL: Key (id)=(update_all_non_ended_shows_metadata) already exists.
mediamanager-postgres | STATEMENT: INSERT INTO apscheduler_jobs (id, next_run_time, job_state) VALUES ($1::VARCHAR, $2, $3)

Filesystem check warning:

mediamanager | ERROR - media_manager.main - run_filesystem_checks(): Hardlink creation failed, falling back to copying files
mediamanager | Traceback (most recent call last):
mediamanager |   File "/app/media_manager/filesystem_checks.py", line 35, in run_filesystem_checks
mediamanager |     test_hardlink.hardlink_to(test_torrent_file)
mediamanager |   File "/usr/local/lib/python3.13/pathlib/_local.py", line 798, in hardlink_to
mediamanager |     os.link(target, self)
mediamanager | OSError: [Errno 18] Invalid cross-device link: '/downloads/.media_manager_test_dir/.media_manager.test.torrent' -> '/downloads/tvshows/.media_manager_test_dir/.media_manager.test.hardlink'

Earlier, before increasing Postgres/SQLAlchemy pool limits locally, the backend also produced:

sqlalchemy.exc.TimeoutError: QueuePool limit of size 5 overflow 10 reached, connection timed out, timeout 30.00

Browser Logs
Not captured yet.

Network-level observations:

  • POST /api/v1/auth/cookie/login returns 204
  • /api/v1/users/me returns 200 immediately after login
  • /web/dashboard/ returns 404 while serving the SPA fallback HTML
  • Later dashboard API calls return 401

Version
v1.12.3

Additional context
The same behavior occurs when accessing MediaManager directly through the published container port, without a Caddy reverse proxy in front of it. This does not appear to be reverse-proxy-specific.

The app appears to serve SvelteKit fallback HTML for /web/ and /web/dashboard/, but with HTTP status 404. That may be related to the blank dashboard and failed client-side routing after successful login.

docker-compose.yaml

services:
  mediamanager:
    image: quay.io/maxdorninger/mediamanager:latest
    container_name: mediamanager
    environment:
      - CONFIG_DIR=/app/config
      - TZ=Europe/Amsterdam
    ports:
      - "8000:8000"
    volumes:
      - /mnt/services/arr-stack/mediamanager-config:/app/config
      - /mnt/services/arr-stack/mediamanager-images:/app/images
      - /mnt/data:/downloads
    depends_on:
      mediamanager-db:
        condition: service_healthy
    restart: unless-stopped

  mediamanager-db:
    image: postgres:17
    container_name: mediamanager-postgres
    environment:
      POSTGRES_USER: MediaManager
      POSTGRES_DB: MediaManager
      POSTGRES_PASSWORD: REDACTED
    volumes:
      - /mnt/services/arr-stack/mediamanager-postgres:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -d $${POSTGRES_DB} -U $${POSTGRES_USER}"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

  prowlarr:
    image: linuxserver/prowlarr:latest
    container_name: prowlarr
    environment:
      - PUID=1000
      - PGID=100
      - TZ=Europe/Amsterdam
    volumes:
      - /mnt/services/arr-stack/prowlarr-config:/config
    ports:
      - "9696:9696"
    restart: unless-stopped

  flaresolverr:
    image: ghcr.io/flaresolverr/flaresolverr:latest
    container_name: flaresolverr
    environment:
      - LOG_LEVEL=info
      - LOG_HTML=false
      - CAPTCHA_SOLVER=none
      - TZ=Europe/Amsterdam
    ports:
      - "8191:8191"
    restart: unless-stopped

config.toml

[misc]
frontend_url = "http://server-ip:8000"
cors_urls = ["http://server-ip:8000"]
image_directory = "/app/images"
tv_directory = "/downloads/tvshows"
movie_directory = "/downloads/movies"
torrent_directory = "/downloads"
development = false

[[misc.tv_libraries]]
name = "TV Shows"
path = "/downloads/tvshows"

[[misc.movie_libraries]]
name = "Movies"
path = "/downloads/movies"

[database]
host = "mediamanager-db"
port = 5432
user = "MediaManager"
password = "REDACTED"
dbname = "MediaManager"

[auth]
email_password_resets = false
token_secret = "REDACTED"
session_lifetime = 86400
admin_emails = ["admin@example.com"]

[auth.openid_connect]
enabled = false
client_id = ""
client_secret = ""
configuration_endpoint = "https://openid.example.com/.well-known/openid-configuration"
name = "OpenID"

[notifications]

[notifications.smtp_config]
smtp_host = "smtp.example.com"
smtp_port = 587
smtp_user = "admin"
smtp_password = "admin"
from_email = "mediamanager@example.com"
use_tls = true

[notifications.email_notifications]
enabled = false
emails = []

[notifications.gotify]
enabled = false
api_key = ""
url = "https://gotify.example.com"

[notifications.ntfy]
enabled = false
url = "https://ntfy.sh/your-topic"

[notifications.pushover]
enabled = false
api_key = ""
user = ""

[torrents]

[torrents.qbittorrent]
enabled = false
host = "http://gluetun"
port = 8085
username = ""
password = ""

[torrents.transmission]
enabled = true
username = "REDACTED"
password = "REDACTED"
https_enabled = false
host = "gluetun"
port = 9091
path = "/transmission/rpc"

[torrents.sabnzbd]
enabled = true
host = "http://sabnzbd"
port = 8080
api_key = "REDACTED"
base_path = "/api"

[indexers]

[indexers.prowlarr]
enabled = true
url = "http://prowlarr:9696"
api_key = "REDACTED"
timeout_seconds = 60

[indexers.jackett]
enabled = false
url = "http://jackett:9117"
api_key = ""
indexers = []
timeout_seconds = 60

[[indexers.title_scoring_rules]]
name = "prefer_h265"
keywords = ["h265", "hevc", "x265", "h.265", "x.265"]
score_modifier = 100
negate = false

[[indexers.title_scoring_rules]]
name = "avoid_cam"
keywords = ["cam", "camrip", "bdscr", "ddc", "dvdscreener", "dvdscr", "hdcam", "hdtc", "hdts", "scr", "screener", "telesync", "ts", "webscreener", "tc", "telecine", "tvrip"]
score_modifier = -10000
negate = false

[[indexers.indexer_flag_scoring_rules]]
name = "prefer_freeleech"
flags = ["freeleech", "freeleech75"]
score_modifier = 100
negate = false

[[indexers.indexer_flag_scoring_rules]]
name = "reject_nuked"
flags = ["nuked"]
score_modifier = -10000
negate = false

[[indexers.scoring_rule_sets]]
name = "default"
libraries = ["ALL_TV", "ALL_MOVIES"]
rule_names = ["prefer_h265", "avoid_cam", "reject_nuked", "prefer_freeleech"]

[metadata]

[metadata.tmdb]
tmdb_relay_url = "https://metadata-relay.dorninger.co/tmdb"
primary_languages = [""]
default_language = "en"

[metadata.tvdb]
tvdb_relay_url = "https://metadata-relay.dorninger.co/tvdb"
  • I understand, that without logs and/or screenshots and a detailed description of the problem, it is very hard to fix bugs.
  • I have checked the documentation for help.
  • I have searched the issues for similar issues and found none.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions