Stash2Plex

:placard: Summary Sync metadata from Stash to Plex with queue-based reliability.
:link: Repository https://github.com/trek-e/Stash2Plex
:information_source: Source URL https://raw.githubusercontent.com/trek-e/Stash2Plex/main/index.yml
:open_book: Install How to install a plugin?

Stash2Plex

Sync metadata from Stash to Plex with queue-based reliability.

Overview

Stash2Plex is a Stash plugin that automatically syncs scene metadata from Stash to Plex. When you update a scene in Stash (title, studio, performers, tags), Stash2Plex queues the change and syncs it to the matching item in your Plex library.

Key features:

  • Persistent queue - Jobs survive Stash restarts; nothing is lost if Stash crashes
  • Automatic retry - Failed syncs retry with exponential backoff
  • Circuit breaker - Protects Plex from being hammered when it’s down
  • Crash recovery - In-progress jobs automatically resume after restart
  • Performance caching - Reduces Plex API calls with disk-backed caching
  • Selective sync - Toggle which metadata fields sync to Plex
  • Sync statistics - Track success rates and timing with batch summaries

Use Stash2Plex if you:

  • Organize your media metadata in Stash
  • Want Plex to reflect the same titles, studios, performers, and tags
  • Need reliable syncing that handles network issues gracefully

Quick Start

Prerequisites:

  • Stash running with PythonDepManager plugin installed
  • Plex Media Server running and accessible from Stash
  • Your Plex authentication token

Get Your Plex Token

  1. Open Plex Web App and sign in
  2. Open any item in your library
  3. Click the three-dot menu and select β€œGet Info”
  4. Click β€œView XML”
  5. In the URL bar, find X-Plex-Token=YOUR_TOKEN_HERE

Alternatively, see Plex’s official guide.

Installation

  1. Download Stash2Plex to your Stash plugins directory:

    cd ~/.stash/plugins
    git clone https://github.com/trek-e/Stash2Plex.git
    

    Or download and extract the ZIP from the releases page.

  2. Reload plugins in Stash:

    Settings > Plugins > Reload Plugins

  3. Configure required settings in Stash:

    Settings > Plugins > Stash2Plex

    Setting Value
    Plex URL http://localhost:32400 (or your Plex server address)
    Plex Token Your X-Plex-Token from above
    Plex Library Name of your Plex library (e.g., Movies)
  4. Test the sync:

    • Edit any scene in Stash (change the title slightly)
    • Check Plex within 30 seconds - the title should update

That’s it! Stash2Plex is now syncing metadata from Stash to Plex.

How It Works

  1. Hook triggers - When you update a scene in Stash, Stash2Plex receives a hook event
  2. Job queued - The sync job is saved to a SQLite-backed persistent queue
  3. Worker syncs - Background worker matches the scene to Plex and applies metadata
  4. Retry on failure - If Plex is down, the job retries with exponential backoff
  5. Dead letter queue - Permanently failed jobs (e.g., no Plex match) go to a DLQ for review

Documentation

Requirements

  • Stash - Any recent version
  • Plex Media Server - Any recent version
  • PythonDepManager - Stash plugin for managing Python dependencies
  • Python dependencies - Installed automatically by PythonDepManager:
    • plexapi - Plex API client
    • pydantic - Data validation
    • tenacity - Retry logic
    • persistqueue - SQLite-backed queue
    • diskcache - Performance caching

Settings Reference

Core Settings

Setting Type Default Description
plex_url string - Plex server URL (required)
plex_token string - Plex authentication token (required)
plex_library string - Plex library name (recommended)
enabled boolean true Enable/disable the plugin

Behavior Settings

Setting Type Default Description
max_retries number 5 Max retry attempts before DLQ
poll_interval number 30 Seconds between queue polls
strict_matching boolean true Skip sync when multiple matches found
preserve_plex_edits boolean false Don’t overwrite existing Plex values
connect_timeout number 5 Plex connection timeout (seconds)
read_timeout number 30 Plex read timeout (seconds)

Field Sync Toggles

Control which metadata fields sync from Stash to Plex. All enabled by default.

Setting Type Default Description
sync_master boolean true Master toggle - when OFF, no fields sync
sync_studio boolean true Sync studio name
sync_summary boolean true Sync summary/details
sync_tagline boolean true Sync tagline
sync_date boolean true Sync release date
sync_performers boolean true Sync performers as actors
sync_tags boolean true Sync tags as genres
sync_poster boolean true Sync poster image
sync_background boolean true Sync background/fanart image
sync_collection boolean true Add to collection by studio name

See Configuration Reference for detailed documentation of all settings.

Push to the Community Repo added here: WIP: Add Stash2Plex plugin by trek-e Β· Pull Request #660 Β· stashapp/CommunityScripts Β· GitHub

Would love feedback/report issues. I have some other fixes I have planned/refinements, as I am using this to learn this stupid vibe code thing that everyone that employs people around me wants you to know. I’m more of a believer than I was a week ago, but do not think this will or should replace people. I can see how it could be a help to someone who knows their stuff, but MBAs can really fuck it up.

I get this error,

26-02-05 01:07:09
Error   
Plugin returned error: No module named 'pydantic'
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex] ModuleNotFoundError: No module named 'pydantic'
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex]     from pydantic import BaseModel, Field, field_validator, ValidationError
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex]   File "/root/.stash/plugins/Stash2Plex/validation/metadata.py", line 8, in <module>
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex]     from validation.metadata import SyncMetadata, validate_metadata
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex]   File "/root/.stash/plugins/Stash2Plex/validation/__init__.py", line 10, in <module>
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex]     from validation.config import validate_config, Stash2PlexConfig
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex]   File "/root/.stash/plugins/Stash2Plex/Stash2Plex.py", line 39, in <module>
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex] Traceback (most recent call last):
2026-02-05 01:07:09
Error   
[Plugin / Stash2Plex] [Stash2Plex] Import error: No module named 'pydantic'

And yes, i have installed β€œPythonDepManager” and reloaded plugins. I even restarted stash. Still same error.

are you running in a container or native?

Which os?

if docker can you run:

docker exec -it pip install -r /root/.stash/plugins/Stash2Plex/requirements.txt which should force it to install, but confused with the PythonDepManager installed why it failed.

Think I addressed it, in docker PythonDepManager needs to be poked by the plugin, it now calls for ensure_import . so the 1.2.1 version has that fix in it so you don’t have to manually run the pip to fix it.

I manually updated the plugin from github for the plugin to 1.2.1 and I am still receiving the same error as milindpatel63. I have tried restarting stash, reloading plugins, etc. I even went in and cd’ed into the Stash2Plex plugin directory and ran pip install -r requirements.txt to manually install pydantic which was successful:

Installing collected packages: persist-queue, typing-inspection, tenacity, pydantic-core, diskcache, annotated-types, pydantic, plexapi
Successfully installed annotated-types-0.7.0 diskcache-5.6.3 persist-queue-1.1.0 plexapi-4.18.0 pydantic-2.12.5 pydantic-core-2.41.5 tenacity-9.1.3 typing-inspection-0.4.2

Weird. I did some more boundary work on trying to capture this, also fixed a sequencing bug that I found and bumped to v1.2.3

I updated the plugin and tried again. I received numerous errors surrounding the Python requirements. I again installed the requirements in the plugin directory and it already stated the requirements were satisfied. I do have a Python3 plugin installed for Unraid which some of the error messages might be pointing to. I added the install command it suggested into my autoexec for the Python3 plugin to see if that would fix it, but no luck. The following error is from my Log.txt file when it ran:

time=β€œ2026-02-06 09:42:03” level=warning msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] pip install persist-queue>=1.1.0 failed: error: externally-managed-environment”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] Γ— This environment is externally managed”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] ╰─> "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     The system-wide python installation should be maintained using the system"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     package manager (apk) only.”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     If the package in question is not packaged already (and hence installable via"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "apk add py3-somepackage"), please consider installing it inside a virtual”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     environment, e.g.:”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     python3 -m venv /path/to/venv"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     . /path/to/venv/bin/activate”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     pip install mypackage”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     To exit the virtual environment, run:"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     deactivate"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     The virtual environment is not deleted, and can be re-entered by re-sourcing"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     the activate file.”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     To automatically manage virtual environments, consider using pipx (from the"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     pipx package).”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] hint: See PEP 668 for the detailed specification.”
time=β€œ2026-02-06 09:42:03” level=warning msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] pip install plexapi>=4.17.0 failed: error: externally-managed-environment”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] Γ— This environment is externally managed”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] ╰─> "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     The system-wide python installation should be maintained using the system"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     package manager (apk) only.”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     If the package in question is not packaged already (and hence installable via"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "apk add py3-somepackage"), please consider installing it inside a virtual”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     environment, e.g.:”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     python3 -m venv /path/to/venv"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     . /path/to/venv/bin/activate”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     pip install mypackage”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     To exit the virtual environment, run:"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     deactivate"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     The virtual environment is not deleted, and can be re-entered by re-sourcing"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     the activate file.”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:03” level=error msg=”\[Plugin / Stash2Plex\]     To automatically manage virtual environments, consider using pipx (from the"
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\]     pipx package).”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.”
time=β€œ2026-02-06 09:42:03” level=error msg=β€œ\[Plugin / Stash2Plex\] hint: See PEP 668 for the detailed specification.”
time=β€œ2026-02-06 09:42:04” level=warning msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] pip install tenacity>=9.0.0 failed: error: externally-managed-environment”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\] Γ— This environment is externally managed”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\] ╰─> "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     The system-wide python installation should be maintained using the system"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     package manager (apk) only.”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     If the package in question is not packaged already (and hence installable via"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "apk add py3-somepackage"), please consider installing it inside a virtual”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     environment, e.g.:”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     python3 -m venv /path/to/venv"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     . /path/to/venv/bin/activate”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     pip install mypackage”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     To exit the virtual environment, run:"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     deactivate"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     The virtual environment is not deleted, and can be re-entered by re-sourcing"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     the activate file.”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:04” level=error msg=”\[Plugin / Stash2Plex\]     To automatically manage virtual environments, consider using pipx (from the"
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\]     pipx package).”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\] note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.”
time=β€œ2026-02-06 09:42:04” level=error msg=β€œ\[Plugin / Stash2Plex\] hint: See PEP 668 for the detailed specification.”
time=β€œ2026-02-06 09:42:05” level=warning msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] pip install pydantic>=2.0.0 failed: error: externally-managed-environment”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\] Γ— This environment is externally managed”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\] ╰─> "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     The system-wide python installation should be maintained using the system"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     package manager (apk) only.”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     If the package in question is not packaged already (and hence installable via"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "apk add py3-somepackage"), please consider installing it inside a virtual”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     environment, e.g.:”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     python3 -m venv /path/to/venv"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     . /path/to/venv/bin/activate”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     pip install mypackage”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     To exit the virtual environment, run:"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     deactivate"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     The virtual environment is not deleted, and can be re-entered by re-sourcing"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     the activate file.”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:05” level=error msg=”\[Plugin / Stash2Plex\]     To automatically manage virtual environments, consider using pipx (from the"
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\]     pipx package).”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\] note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.”
time=β€œ2026-02-06 09:42:05” level=error msg=β€œ\[Plugin / Stash2Plex\] hint: See PEP 668 for the detailed specification.”
time=β€œ2026-02-06 09:42:06” level=warning msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] pip install diskcache>=5.6.0 failed: error: externally-managed-environment”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] Γ— This environment is externally managed”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] ╰─> "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     The system-wide python installation should be maintained using the system"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     package manager (apk) only.”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     If the package in question is not packaged already (and hence installable via"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "apk add py3-somepackage"), please consider installing it inside a virtual”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     environment, e.g.:”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     python3 -m venv /path/to/venv"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     . /path/to/venv/bin/activate”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     pip install mypackage”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     To exit the virtual environment, run:"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     deactivate"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     The virtual environment is not deleted, and can be re-entered by re-sourcing"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     the activate file.”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     "
time=β€œ2026-02-06 09:42:06” level=error msg=”\[Plugin / Stash2Plex\]     To automatically manage virtual environments, consider using pipx (from the"
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\]     pipx package).”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] note: If you believe this is a mistake, please contact your Python installation or OS distribution provider. You can override this, at the risk of breaking your Python installation or OS, by passing --break-system-packages.”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] hint: See PEP 668 for the detailed specification.”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] Missing required dependencies: \[β€˜persistqueue’, β€˜plexapi’, β€˜tenacity’, β€˜pydantic’, β€˜diskcache’\]”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] Stash is using Python: /usr/bin/python3”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œ\[Plugin / Stash2Plex\] \[Stash2Plex\] To fix, run:  /usr/bin/python3 -m pip install persist-queue>=1.1.0 plexapi>=4.17.0 tenacity>=9.0.0 pydantic>=2.0.0 diskcache>=5.6.0”
time=β€œ2026-02-06 09:42:06” level=error msg=β€œScene.Update.Post \[Stash2Plex\]: returned error: Missing dependencies: persistqueue, plexapi, tenacity, pydantic, diskcache. Install with: /usr/bin/python3 -m pip install persist-queue>=1.1.0 plexapi>=4.17.0 tenacity>=9.0.0 pydantic>=2.0.0 diskcache>=5.6.0”

OK, made some changes that hopefully will address that. I’m using a different container and apparently official one uses ubuntu which makes pip get aggressive? least that’s what I’m reading. 1.2.7 with a couple of other things I found and fixed is up.

I updated to version 1.2.10, and Stash2Plex is successfully updating the Metadata on Plex. I can confirm the plugin is successfully updating the metadata correctly and fully, much better than the Plex_Sync plugin.

However, it is particularly slow. I was updating a library with 169 scenes and after an hour and a half it was only about a quarter of the way through. I have noticed 2 different things that are causing that to take some time:

Library scans: My Plex utilizes multiple libraries for the adult content. ie. Misc, Sexart, Sinfulxxx, Tushy. It doesn’t appear the setting allows you to enter multiple Plex Libraries to limit the scan to and can only have a single library input. As a result it has to go through all 15 of my libraries in order to find the one in question. This isn’t a problem, but being able to support multiple libraries, could help.

The bigger impact, looks to be the plugin repeatedly updating the same scenes over and over again. It seems like it will continue to update all previously updated scenes in the batch for every next scene. ex: Scene 1 search, Scene 1 updated, Scene 2 search, Scene 1 updated, Scene 2 updated. Scene 3 search, Scene 1 updated, Scene 2 updated, Scene 3 updated. There are constant β€œCache Hits” within the logs.

It seems like the Pending Queue is not being cleared when the plugin completes it. I ran an update for a page worth of scenes (40). It took about an hour to finish, and afterwards I ran a task to view the Pending Queue. 1 showed as In Process and it had 80 in the pending queue still. I then ran a Process Queue task and it completed a little over half before timing out. Rerunning the view queue still shows 1 in process and 80 in pending. After running the clear pending queue task it still leaves the 1 in progress and I see that item update every time the plugin runs.

The logs are pretty extensive but I would be happy to provide whatever you may need.

It would seem that the Sync all Scenes to Plex works significantly more error free in comparison to selecting all scenes from a studio and submitting a bulk update to those scenes via Stash.

Hi All. The syncing issues had been bugging me so I was already working on those. But I had not considered that there would be multiple libraries. I use collections to sort by. So I pushed two updates. There is a 1.2.x bug fix trying to address that.

Then I spent some time updating to get it to allow you to select multiple libraries. That version starts with 1.3. I don’t have a great test for it on my system, so if you don’t need it go with the latest 1.2.x line for now

But if those of you who organize by library could see if the 1.3 version lets you select how you want, and if not please tell me what I might have done wrong in my interpretation of it. I decided the easiest way was for you to comma separate the names I didn’t want to try and query and present a list. I may play with that to see if that’s something you can do as a plugin or not later.

Let me know what you run into. Thanks for such a detailed explanation though it helped me figure it out pretty quickly.

I was able to successfully get the scan through the entirety of my library (3200 scenes). I will say this is a very slick plugin and I like its functionality significantly better than the Plex_Sync plugin. Being able to choose the Plex library type, which allows me to choose what the poster orientation is (Movies Vertical, Personal Media Horizontal) has been exactly what I have been looking for.

A few things I ran into:

Edit: I see that you released version 1.3.1, these may or may not be fixed with your version update.

I ran into two items that were causing the plugin to stop processing.

  1. Items that I had manually been messing with the match within Plex were not able to be matched/synced. I could not figure out exactly what I was doing to cause this but if/when I run into it again I will provide additional details.

  2. The items impacted by the above time out I then deleted within stash. This does not remove those items from the existing pending queue. So when I tried to run the Process Queue task it kept hitting a circuit breaker on those items.

It did not seem like these instances were incrementing the DLQ counter to eventually be moved to the Dead Letter Queue. Unfortunately, I was not actually able to capture the logs or details on these two scenarios, So I have to work from memory and I could be incorrect. I will follow up if/when I run into it again. I ended up having to clear the pending queue to get rid of these entries and then rerun the sync.

And lastly, the pending queue frequently does not clear out items it completes. During the full scan it ran into a circuit breaker during the scan. When it started over It started again several hundred entries before the item that triggered the circuit breaker. Additionally, when the matching finished, I ran the Pending Queue stats and it still showed all those items still in the pending queue. Running the Process Queue task has it repeat those items again and it completed successfully again with the item still in the queue.

Also the limiting of libraries worked perfectly as far as I can tell.

I pushed out 1.3.2.

It has a new log option, full debug. If you want, turn it on, try a few things, turn it off, and open an issue on the GitHub and lets see if we can find what’s going on, I’m running it on mine and will use that, but the more the merrier on data.

**Now up to v1.4.3. The new feature I added was

Gap Detection Engine**: Detects three types of metadata gaps between Stash and Plex β€” empty metadata (Plex has no data but Stash does), stale syncs (Stash updated since last sync), and missing items (Stash scenes with no Plex match). Uses batch processing and deduplication for large libraries.

The two point releases were minor fix/code optimizations. This was mostly a β€˜I need’ feature as my plex library is several years old and some of my older files didn’t have some of the newer things I was syncing. It basically tries in the background, caches the try as to not go nuts. I’m watching for any performance hits but I believe my circuit breakers are working and keeping it from dragging everything down.