Server Version#: 1.41.3
Player Version#: – not relevant
I’m documenting this information for the unlikely chance this gets resolved. Either way, I’d rather this information occupy the public void than my personal backlog.
PMS Docker on MacOS
It works pretty well, especially when configured with a docker-compose.yml file, using the appropriate bridge setup, among other things. It’s worth noting this is operating on Apple Silicon (M2 Max). Given there are not many clear examples of this online, here’s my working file. This should work for pretty much anyone who wants to run PMS in Docker on a MacOS host.
The only changes needed are PLEX_CLAIM and setting your host’s local IP address from something that is not my own, which is 192.168.18.3. Of course, the volumes paths on the host machine on the left side need to be updated as well. Other than that, the ADVERTISE_IP and ALLOWED_NETWORKS configurations are the addresses of first the docker container, and secondly the host machine, both of which are essential, especially for a validated remote connection. The only port needed is the one configured.
This works great. Media streams flawlessly, both locally and remotely.
services:
plex:
container_name: plex
image: plexinc/pms-docker:latest
restart: unless-stopped
environment:
- TZ=Etc/UTC
- PLEX_CLAIM=XXXX
- ADVERTISE_IP=https://172.19.0.2:32400/,https://192.168.18.3:32400/
- ALLOWED_NETWORKS=172.19.0.0/16,192.168.18.0/24
hostname: PlexServer
ports:
- 32400:32400/tcp
volumes:
- ${HOME}/.local/share/plexmediaserver/config:/config
- ${TMPDIR}/plexmediaserver/transcode:/transcode
- "${HOME}/Library/Mobile Documents/com~apple~CloudDocs/Media:/data"
networks:
plex:
driver: bridge
The problem
Some of the more observant may have taken note of the host’s :/data path side. This is the path to iCloud Drive’s data. Assuming all of the files have not been “optimized” off the local device, PMS will scan all of these files and play them (their local copies) just fine.
The problem occurs when files have been “optimized.” In other words, they have either automatically been offloaded from the local device, or a user explicitly chose to use the “Remove Download” context option on a given directory or file, which “optimizes” local device storage by essentially replacing the full file with a simple empty reference that is maybe a few bytes. For the unwitting and GUI-reliant user, there’s really no distinction: the file is still there, but it’s just not occupying space on the local device. Magic. If later a user chooses to click on the file in Finder, MacOS’ deep filesystem integration with iCloud Drive will then trigger a download seamlessly behind the scenes, holding the current process until the clicked file is downloaded, at which point it then opens in its configured application. This is pretty great and works well for most native apps.
However, stack on a layer like Docker, which typically runs some GNU/Linux flavor in a container, and mount a volume that has this magical iCloud Drive functionality baked into it from the MacOS host, and that container’s OS could not care less what filesystem magic the host provides. It simply sees a bunch of inodes with various file extensions. This is totally understandable.
What’s also very understandable is that if this container running PMS then runs a typical library scan of a given directory, a reasonable expectation is that it contains a bunch of media-related files, with extensions like mkv and mp4 and maybe even avi for you old-hats out there. PMS’ scanner will see these files and eat them up, so to speak. Great. BUT, PMS does not expect those files that appear to be media files to actually be a bunch of near-zero-length byte files. PMS’ scanner can make enough assumptions about the file based on its filename, but it generally wants to know a lot more. For example, it probably wants to create a hash of the file for a number of reasons, like deduplication, fingerprinting and whatever else. It’s at this point that the PMS library scanner crashes and becomes incapable of recovering, because this sudden attempt to open up this byte-size file with no meaningful file headers inside also happens to corrupt the library DB, which then prevents the entire PMS instance from booting up ever again, until the DB is repaired or simply nuked.
I think we all understand the problem. I’m using fancy filesystem nonsense from Apple. Yeah, yeah. Get it out of your system. ![]()
But hear me out now.
A possible solution
Is it too wild an expectation that the PMS library scanner would at the very least not so catastrophically crash and burn when it opens up a zero-length file? Couldn’t it just catch this error/exception and cease attempting to build out a hash of the file, consider it an oddball, but at the very least scan the thing in with what it has, which is really just a name, year, and file extension, at minimum? Couldn’t these “placeholder” files essentially be treated the same as those files that have already been scanned in but their local device is unavailable, at which point one could choose to clear out any of these orphans, or simply re-attach the device?
I’m not asking for PMS’ library scanner to know or care about an iCloud Drive path from a Docker container (of course I would enthusiastically welcome it, though), but it should at the very least not treat these dud/placeholder/orphan files as anything more than benign; a zero-length file shouldn’t be a landmine that not only takes out your foot, but is literally a fatal blow.
Can this be fixed?
It’s been years since I used Plex, but I’ve had lifetime for what feels like a lifetime, and I recently found a need to fire it up again. If it’s possible for this error to be handled in a way that allows the PMS scanner to just skip and continue, I’d be so damn grateful.
Thanks!
Some debug log output
I don’t remember the name of the logs, but these were the highlights I came across when trying to figure out why PMS would just die and never recover. I replaced the name of the media with “Foobar Guys (2011),” which is just for demonstration purposes.
Jan 13, 2025 23:29:23.044 [281473042493496] DEBUG - Analyzing media parts for item 60 (Foobar Guys): 83
Jan 13, 2025 23:29:23.044 [281473042493496] ERROR - Exception computing file hashes: Error reading block from /data/movies/Foobar Guys (2011)/Foobar.Guys.2011.mkv
Jan 13, 2025 20:37:18.205 [2814734772553921] DEBUG - Scanner: Processing directory /data/movies/Foobar Guys (2011) (parent: yes)
Jan 13, 2025 20:37:18.206 [2814734269237441] ERROR - Exception computing file hashes: Error reading block from /data/movies/Foobar Guys (2011)/Foobar.Guys.2011.mkv
Jan 13, 2025 20:37:18.209 [2814734772553921] ERROR - SQLITE3:0xffffad780850, 11, database corruption at line 69165 of [a29f994989]
Jan 13, 2025 20:37:18.209 [2814734772553921] ERROR - SQLITE3:0xffffad780850, 11, statement aborts at 8: Iselect distinct media_parts.file, media_parts.size, media_parts.updated_at, media_parts.deleted_at from media_parts join media_items on media_items. id = media_parts-media_item_id where media_parts. directory_id = ? and media_items. section_location_id = ? database disk image is malformed
Jan 13, 2025 20:37:18.209 [2814734772553921] ERROR - Exception caught determining whether we could skip 'Footer Guys (2011) ' ~ sqlite3_statement_backend:: loadRS: database disk image is malformed
It’s worth noting that this is not a one-off. Given the benefits of Docker, I went through this process five times with a clean container each time, inching closer to understanding why, and then finally putting my thoughts together. I can reproduce this problem with total consistency.