Jellyfin is sitting in my Docker stack right next to Immich and Frigate, and most days it just works. Other days, I’m staring at a blank dashboard or watching library scans hang for two hours. The frustrating part is that Jellyfin troubleshooting documentation assumes you already know where to look. This post covers five actual errors I hit while running Jellyfin in production, what I tried first, and what finally fixed them.

Error 1: Jellyfin Container Exits Immediately with Permission Denied
I set up Jellyfin in Docker, mapped my media volumes, and watched it crash before it even showed a web UI. The logs were the real problem: permission denied on /var/lib/jellyfin. This happens because Docker runs the Jellyfin container as a specific user (usually jellyfin:jellyfin, UID 117:125), and if your host directories aren’t readable by that user, you’re done before you start.
First, I tried the obvious fix: chmod 777 on everything. That worked temporarily, but I knew it was wrong. A proper Jellyfin setup needs proper ownership. The real solution is either running the container with the right UID/GID or making sure your media directories are owned by the jellyfin user.
Here’s what actually worked in my Docker Compose:
services:
jellyfin:
image: jellyfin/jellyfin:latest
container_name: jellyfin
user: "117:125"
volumes:
- /mnt/media/movies:/media/movies:ro
- /mnt/media/tv:/media/tv:ro
- jellyfin-config:/config
environment:
- JELLYFIN_DATA_DIR=/config
restart: unless-stopped
volumes:
jellyfin-config:
driver: local
But I also had to fix the host side. Before starting the container, I ran sudo chown -R 117:125 /mnt/media on my media directory. The UID 117 and GID 125 are Jellyfin’s defaults in the image; check your own image by running it once and checking /etc/passwd inside the container if yours differ. After that, the container started cleanly and scanned libraries without hanging on permission checks.
Error 2: Libraries Scan But Show Zero Items
This one took me longer to debug than I want to admit. Jellyfin was running, I could see the library folders in settings, but when I navigated to Movies or TV, the dashboards were empty. The scanner wasn’t throwing errors, just silently finding nothing.
I checked the logs and found entries like: Skipping file because it does not have a file extension. Turns out my media folder had subdirectories with lowercase names and mixed-case files, and something about how I’d structured them was confusing Jellyfin’s naming parser. But that wasn’t the real issue.
The actual problem was that Jellyfin’s library scanning runs on a schedule, and that schedule had already passed. I’d configured the library hours ago, but the first scan wasn’t automatic. The fix was embarrassingly simple: go to Settings > Libraries, select the library, and click the refresh button manually. It scanned immediately and found 400+ movies. After that, I set up a more aggressive schedule (Administration > Scheduled Tasks > Library Scan every 6 hours instead of the default 24) so future additions wouldn’t sit invisible for a day.
One more thing I changed: I made sure my folder structure followed standard conventions. Jellyfin’s metadata matcher works best with clean paths like /media/movies/Movie Title (Year) or /media/tv/Show Name/Season 01. Weird nested structures or files directly in the root folder don’t always parse correctly.
Error 3: Playback Works Locally But Fails Over Remote Access
This one’s less of a crash and more of a frustration. I’d set up Jellyfin behind a reverse proxy (nginx with a valid SSL cert), and streaming locally on LAN worked perfectly. The moment I tried to play something from my phone over the internet, I’d get a generic playback error or an infinite buffering loop.
The issue was transcoding. Jellyfin was set up to transcode on-the-fly for remote clients (sensible, to save bandwidth), but my CPU couldn’t keep up. The transcoding process would time out, the connection would drop, and the client would fail. I checked /var/log/jellyfin/log_*.log inside the container and saw entries about ffmpeg subprocess crashes.
I had two options: beef up the hardware or disable unnecessary transcoding. I went with a middle path. In Settings > Playback, I set remote streaming to require H.264 video (which most of my media already was) and limited audio to AAC stereo. I left transcoding enabled for the few files that needed it, but set maximum bitrate caps per device. The configuration looked like this in the dashboard:
- Max streaming bitrate (Remote): 5000 Kbps
- Transcoding temp directory: /transcodes (on fast SSD, not the spinning media drive)
- Segment length: 6 seconds (default is fine, but affects buffer behavior)
After that, remote playback stopped timing out. It’s not perfect — some files still transcode, and I can see the CPU spike — but it’s stable. If I upgrade to a better CPU later, I’ll relax these limits.
Error 4: “FFmpeg Not Found” During Library Scan
Jellyfin relies on FFmpeg for a lot of background work: extracting metadata, generating thumbnails, and preparing for transcoding. I ran into a situation where the scanner would fail on certain video files with the error FFmpeg not found or not executable.
This one’s usually a path problem. Jellyfin’s Docker image includes FFmpeg, but if you’ve customized the container or used an older image, it might be missing. First check was to enter the container and look for it:
docker exec jellyfin which ffmpeg
It returned nothing. So FFmpeg wasn’t installed in the image I was using. I switched to the official jellyfin/jellyfin:latest tag, which includes FFmpeg by default. If you’re building your own image or using a minimal variant, you need to install it:
apt-get update && apt-get install -y ffmpeg
in your Dockerfile. After re-pulling the official image, the scans completed and metadata extraction worked. The thumbnail generation also sped up significantly.
One caveat: FFmpeg in Docker containers sometimes lacks hardware acceleration support (NVIDIA CUDA, Intel Quick Sync). If you want HW transcoding, you need to pass the device through and install the right driver version inside the container. That’s a separate rabbit hole, but it’s worth knowing the default setup is CPU-only.
Error 5: Dashboard Fails to Load After Update
I was running Jellyfin 10.8.x without issues, then pulled the latest tag and found the web UI wouldn’t load. The container was running, the backend was responding to pings, but navigating to the dashboard showed a blank page or a 500 error.
The problem was a database schema mismatch. When you upgrade Jellyfin between major versions, it migrates the database automatically, but if something goes wrong during that migration, the frontend and backend get out of sync.
My fix was to clear the browser cache and hard-refresh (Ctrl+Shift+R on most browsers), which solved it for about 20% of attempts. The other 80% of the time, I needed to look at the container logs more carefully:
docker logs jellyfin | grep -i "error|exception"
One time, I found a database lock error. I stopped the container, removed the lock file in the config directory (jellyfin.db-wal and jellyfin.db-shm), and restarted. That freed things up.
Another time, it was a permissions issue on the config volume. The upgrade process had written files as root instead of the jellyfin user, which caused subsequent startup checks to fail. I fixed it with docker exec jellyfin chown -R jellyfin:jellyfin /config.
The lesson here: upgrade Jellyfin during a maintenance window when you have time to troubleshoot. The releases are generally stable, but schema migrations can be finicky. I now always back up the config volume before upgrading, just in case.
What Helped Most: Better Logging and Patience
Looking back, I wasted time on most of these because I wasn’t reading the logs carefully enough. The error messages are there; they’re just buried in the Jellyfin logs or Docker output. Setting up persistent logging to a file and running tail -f while testing has saved me hours. I also started documenting what I changed and when, which makes rolling back upgrades or diagnosing regressions much faster.
Jellyfin is solid software, but it’s not magic. Most problems come down to permissions, networking, or resource constraints. None of these were show-stoppers once I understood what was actually failing.
FAQ
Can Jellyfin run on a Raspberry Pi?
Yes, but with caveats. A Pi 4 or 5 can run Jellyfin and stream to local clients fine, but hardware transcoding isn’t reliable and CPU transcoding will max out quickly. It’s best used as a display server for pre-encoded content, not as a transcoding powerhouse.
How much RAM does Jellyfin need?
Minimum 512 MB, but 2 GB is more practical if you’re indexing large libraries or allowing multiple simultaneous connections. Scanning 10,000+ items works but is slow on less than 1 GB.
Does Jellyfin support AI-powered metadata like Whisper for subtitles?
Jellyfin itself doesn’t include Whisper built-in, but you can integrate it via plugins or external tools. Some community members have set up Whisper as a separate service and piped output to Jellyfin. The native metadata fetching is traditional (TheTVDB, IMDb), not AI-generated.
What’s the difference between Jellyfin and Plex?
Jellyfin is open-source and self-hosted; Plex is proprietary and cloud-connected. Jellyfin gives you full control and privacy, but Plex has better UI polish and more aggressive feature development. Both serve media fine.
Do I need SSL certificates for Jellyfin behind a reverse proxy?
Not required for LAN-only access, but strongly recommended if you’re exposing it to the internet. Use Let’s Encrypt (free) or another certificate authority. Many browsers and apps will reject unencrypted HTTPS traffic, and you’ll get playback errors on remote clients.
Explore Jellyfin in our AI Homelab Toolkit.