Taxel / PlexTraktSync

A python script that syncs the movies, shows and ratings between trakt and Plex (without needing a PlexPass or Trakt VIP subscription)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Need show attribute, but it is missing for

nemchik opened this issue · comments

Confirmation

  • I have read the README.md on the project homepage
  • I have checked if identical issue already exists
  • I have tried downgrading to find version that can be used as a workaround

The problem

Trying to sync series results in an error (see trace logs)

Steps to reproduce the behavior

running ghcr.io/taxel/plextraktsync:latest (on unraid) which is version 0.28.18 as of writing
docker exec -it plextraktsync sh then plextraktsync or plextraktsync sync

Error trace / logs

ERROR    Need show attribute, but it is missing for <tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01>
         ╭───────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────╮
         │ /app/plextraktsync/cli.py:26 in wrap                                                                        │
         │                                                                                                             │
         │    23 │   │   │   cmd = getattr(module, name)                                                               │
         │    24 │   │   │                                                                                             │
         │    25 │   │   │   try:                                                                                      │
         │ ❱  26 │   │   │   │   cmd(*args, **kwargs)                                                                  │
         │    27 │   │   │   except EOFError as e:                                                                     │
         │    28 │   │   │   │   raise ClickException(f"Program requested terminal, No terminal is                     │
         │       connected: {e}")                                                                                      │
         │    29 │   │   │   except ClickException as e:                                                               │
         │                                                                                                             │
         │ /app/plextraktsync/commands/sync.py:68 in sync                                                              │
         │                                                                                                             │
         │   65 │   │   │   w.print_plan(print=logger.info)                                                            │
         │   66 │   │   if dry_run:                                                                                    │
         │   67 │   │   │   logger.info("Enabled dry-run mode: not making actual changes")                             │
         │ ❱ 68 │   │   runner.sync(walker=w, dry_run=config.dry_run)                                                  │
         │   69                                                                                                        │
         │                                                                                                             │
         │ /app/plextraktsync/sync.py:80 in sync                                                                       │
         │                                                                                                             │
         │    77 │   │   │   episode_trakt_ids = set()                                                                 │
         │    78 │   │   │   for episode in walker.find_episodes():                                                    │
         │    79 │   │   │   │   self.sync_collection(episode, dry_run=dry_run)                                        │
         │ ❱  80 │   │   │   │   self.sync_ratings(episode, dry_run=dry_run)                                           │
         │    81 │   │   │   │   self.sync_watched(episode, dry_run=dry_run)                                           │
         │    82 │   │   │   │   if not is_partial:                                                                    │
         │    83 │   │   │   │   │   trakt_lists.add_to_lists(episode)                                                 │
         │                                                                                                             │
         │ /app/plextraktsync/sync.py:125 in sync_ratings                                                              │
         │                                                                                                             │
         │   122 │   │   if not self.config.sync_ratings:                                                              │
         │   123 │   │   │   return                                                                                    │
         │   124 │   │                                                                                                 │
         │ ❱ 125 │   │   if m.plex_rating is m.trakt_rating:                                                           │
         │   126 │   │   │   return                                                                                    │
         │   127 │   │                                                                                                 │
         │   128 │   │   rating_priority = self.config["rating_priority"]                                              │
         │                                                                                                             │
         │ /usr/local/lib/python3.12/functools.py:995 in __get__                                                       │
         │                                                                                                             │
         │    992 │   │   │   raise TypeError(msg) from None                                                           │
         │    993 │   │   val = cache.get(self.attrname, _NOT_FOUND)                                                   │
         │    994 │   │   if val is _NOT_FOUND:                                                                        │
         │ ❱  995 │   │   │   val = self.func(instance)                                                                │
         │    996 │   │   │   try:                                                                                     │
         │    997 │   │   │   │   cache[self.attrname] = val                                                           │
         │    998 │   │   │   except TypeError:                                                                        │
         │                                                                                                             │
         │ /app/plextraktsync/media/Media.py:220 in plex_rating                                                        │
         │                                                                                                             │
         │   217 │   def plex_rating(self):                                                                            │
         │   218 │   │   if self.media_type == "episodes" and not self.plex.is_discover:                               │
         │   219 │   │   │   if not self.show:                                                                         │
         │ ❱ 220 │   │   │   │   raise RuntimeError(f"Need show attribute, but it is missing for {self}")              │
         │   221 │   │   │   show_id = self.show.plex.item.ratingKey                                                   │
         │   222 │   │   else:                                                                                         │
         │   223 │   │   │   show_id = None                                                                            │
         ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
         RuntimeError: Need show attribute, but it is missing for
         <tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01>
Error: Error running sync command: Need show attribute, but it is missing for <tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01>

Expected behavior

Sync should complete without errors

Inspect of problematic items

plextraktsync inspect tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01
PlexTraktSync [0.28.18]
ERROR    Unable to create PlexId: tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01
         ╭───────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────╮
         │ /app/plextraktsync/cli.py:26 in wrap                                                                        │
         │                                                                                                             │
         │    23 │   │   │   cmd = getattr(module, name)                                                               │
         │    24 │   │   │                                                                                             │
         │    25 │   │   │   try:                                                                                      │
         │ ❱  26 │   │   │   │   cmd(*args, **kwargs)                                                                  │
         │    27 │   │   │   except EOFError as e:                                                                     │
         │    28 │   │   │   │   raise ClickException(f"Program requested terminal, No terminal is                     │
         │       connected: {e}")                                                                                      │
         │    29 │   │   │   except ClickException as e:                                                               │
         │                                                                                                             │
         │ /app/plextraktsync/commands/inspect.py:107 in inspect                                                       │
         │                                                                                                             │
         │   104 │   print = factory.print                                                                             │
         │   105 │   print(f"PlexTraktSync [{factory.version.full_version}]")                                          │
         │   106 │                                                                                                     │
         │ ❱ 107 │   for plex_id in expand_plexid(inputs):                                                             │
         │   108 │   │   inspect_media(plex_id)                                                                        │
         │   109                                                                                                       │
         │                                                                                                             │
         │ /app/plextraktsync/util/expand_id.py:39 in expand_plexid                                                    │
         │                                                                                                             │
         │   36 │   from plextraktsync.plex.PlexIdFactory import PlexIdFactory                                         │
         │   37 │                                                                                                      │
         │   38 │   for id in input:                                                                                   │
         │ ❱ 39 │   │   yield PlexIdFactory.create(id)                                                                 │
         │   40                                                                                                        │
         │   41                                                                                                        │
         │   42 def expand_id(input):                                                                                  │
         │                                                                                                             │
         │ /app/plextraktsync/plex/PlexIdFactory.py:18 in create                                                       │
         │                                                                                                             │
         │   15 │   │   elif key.startswith("plex://"):                                                                │
         │   16 │   │   │   return cls.from_plex_guid(key)                                                             │
         │   17 │   │                                                                                                  │
         │ ❱ 18 │   │   raise RuntimeError(f"Unable to create PlexId: {key}")                                          │
         │   19 │                                                                                                      │
         │   20 │   @classmethod                                                                                       │
         │   21 │   def from_plex_guid(cls, id):                                                                       │
         ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
         RuntimeError: Unable to create PlexId: tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01
Error: Error running inspect command: Unable to create PlexId: tvdb:157141:Episode:216124:Mobile-Suit-Gundam-S-s01e01

Workarounds

Note that #1462 is similar and recommends downgrading to 0.26.0 which is incompatible with the config from 0.28.18 and references a fix in #1463 which doesn't seem to apply here. The code in question seems to be

if self.media_type == "episodes" and not self.plex.is_discover:
if not self.show:
raise RuntimeError(f"Need show attribute, but it is missing for {self}")
which looks to have been introduced in #1792

Tried 0.28.16 and 0.28.15 (which should both be before #1792 merged) and got a different error:

ERROR    'NoneType' object has no attribute 'plex'
         ╭───────────────────────────────────── Traceback (most recent call last) ─────────────────────────────────────╮
         │ /app/plextraktsync/cli.py:26 in wrap                                                                        │
         │                                                                                                             │
         │    23 │   │   │   cmd = getattr(module, name)                                                               │
         │    24 │   │   │                                                                                             │
         │    25 │   │   │   try:                                                                                      │
         │ ❱  26 │   │   │   │   cmd(*args, **kwargs)                                                                  │
         │    27 │   │   │   except EOFError as e:                                                                     │
         │    28 │   │   │   │   raise ClickException(f"Program requested terminal, No terminal is                     │
         │       connected: {e}")                                                                                      │
         │    29 │   │   │   except ClickException as e:                                                               │
         │                                                                                                             │
         │ /app/plextraktsync/commands/sync.py:68 in sync                                                              │
         │                                                                                                             │
         │   65 │   │   │   w.print_plan(print=logger.info)                                                            │
         │   66 │   │   if dry_run:                                                                                    │
         │   67 │   │   │   logger.info("Enabled dry-run mode: not making actual changes")                             │
         │ ❱ 68 │   │   runner.sync(walker=w, dry_run=config.dry_run)                                                  │
         │   69                                                                                                        │
         │                                                                                                             │
         │ /app/plextraktsync/sync.py:80 in sync                                                                       │
         │                                                                                                             │
         │    77 │   │   │   episode_trakt_ids = set()                                                                 │
         │    78 │   │   │   for episode in walker.find_episodes():                                                    │
         │    79 │   │   │   │   self.sync_collection(episode, dry_run=dry_run)                                        │
         │ ❱  80 │   │   │   │   self.sync_ratings(episode, dry_run=dry_run)                                           │
         │    81 │   │   │   │   self.sync_watched(episode, dry_run=dry_run)                                           │
         │    82 │   │   │   │   if not is_partial:                                                                    │
         │    83 │   │   │   │   │   trakt_lists.add_to_lists(episode)                                                 │
         │                                                                                                             │
         │ /app/plextraktsync/sync.py:125 in sync_ratings                                                              │
         │                                                                                                             │
         │   122 │   │   if not self.config.sync_ratings:                                                              │
         │   123 │   │   │   return                                                                                    │
         │   124 │   │                                                                                                 │
         │ ❱ 125 │   │   if m.plex_rating is m.trakt_rating:                                                           │
         │   126 │   │   │   return                                                                                    │
         │   127 │   │                                                                                                 │
         │   128 │   │   rating_priority = self.config["rating_priority"]                                              │
         │                                                                                                             │
         │ /usr/local/lib/python3.12/functools.py:995 in __get__                                                       │
         │                                                                                                             │
         │    992 │   │   │   raise TypeError(msg) from None                                                           │
         │    993 │   │   val = cache.get(self.attrname, _NOT_FOUND)                                                   │
         │    994 │   │   if val is _NOT_FOUND:                                                                        │
         │ ❱  995 │   │   │   val = self.func(instance)                                                                │
         │    996 │   │   │   try:                                                                                     │
         │    997 │   │   │   │   cache[self.attrname] = val                                                           │
         │    998 │   │   │   except TypeError:                                                                        │
         │                                                                                                             │
         │ /app/plextraktsync/media/Media.py:217 in plex_rating                                                        │
         │                                                                                                             │
         │   214 │                                                                                                     │
         │   215 │   @cached_property                                                                                  │
         │   216 │   def plex_rating(self):                                                                            │
         │ ❱ 217 │   │   show_id = self.show.plex.item.ratingKey if self.media_type == "episodes" and not              │
         │       self.plex.is_discover else None                                                                       │
         │   218 │   │   return self.plex.rating(show_id)                                                              │
         │   219 │                                                                                                     │
         │   220 │   def trakt_rate(self):                                                                             │
         ╰─────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
         AttributeError: 'NoneType' object has no attribute 'plex'
Error: Error running sync command: 'NoneType' object has no attribute 'plex'

Install method

Unraid installation (not supported)

Config file contents

plextraktsync config
# Config File: /app/config/config.yml
cache:
  path: /app/config/trakt_cache
excluded-libraries:
- Private
- Family Holidays
config:
  dotenv_override: true
plex:
  timeout: 30
logging:
  append: true
  console_time: false
  debug: false
  filename: plextraktsync.log
  filter_loggers: null
  filter: null
sync:
  rating_priority: plex
  plex_to_trakt:
    collection: true
    clear_collected: false
    ratings: true
    watched_status: true
    watchlist: true
  trakt_to_plex:
    liked_lists: true
    ratings: true
    watched_status: true
    watchlist: true
    watchlist_as_playlist: false
watch:
  add_collection: false
  remove_collection: false
  scrobble_threshold: 80
  username_filter: true
  media_progressbar: true
xbmc-providers:
  movies: imdb
  shows: tvdb

Version

0.28.18

Python Version

3.12.2

Plex Server Version

1.40.0.7998

Operating System and Version

Linux-6.1.74-Unraid-x86_64-with

p.s. i did fix match on the show in question (it was already matched) and then also refreshed metadata within plex and it did not resolve the issue.

Also here are some log warnings preceding the trace error:

WARNING  Gundam Build Divers Re:Rise/s01e01/Wandering Core Gundam (2019): Skipping <PlexGuid:tvdb://7345555> not found
         on Trakt
WARNING  Gundam Build Divers Re:Rise/s01e02/Unknown Mission (2019): Skipping <PlexGuid:tvdb://7398860> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s01e03/A Place To Protect (2019): Skipping <PlexGuid:tvdb://7400322> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s01e04/Wounded Wings (2019): Skipping <PlexGuid:tvdb://7400323> not found on Trakt
WARNING  Gundam Build Divers Re:Rise/s01e05/Now Spread Your Wings (2019): Skipping <PlexGuid:tvdb://7418652> not found
         on Trakt
WARNING  Gundam Build Divers Re:Rise/s01e06/Hero on the Brink (2019): Skipping <PlexGuid:tvdb://7418653> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s01e07/Battered Crown (2019): Skipping <PlexGuid:tvdb://7418654> not found on Trakt
WARNING  Gundam Build Divers Re:Rise/s01e08/Duty and Illusion (2019): Skipping <PlexGuid:tvdb://7418655> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s01e09/Abyss of Isolation (2019): Skipping <PlexGuid:tvdb://7459894> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s01e10/The Ones Who Breathe There (2019): Skipping <PlexGuid:tvdb://7471263> not
         found on Trakt
WARNING  Gundam Build Divers Re:Rise/s01e11/Last Mission (2019): Skipping <PlexGuid:tvdb://7481650> not found on Trakt
WARNING  Gundam Build Divers Re:Rise/s01e12/The Shuddering World (2019): Skipping <PlexGuid:tvdb://7491370> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s01e13/Somewhere in This Universe (2019): Skipping <PlexGuid:tvdb://7501971> not
         found on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e01/Encounters, and Then… (2020): Skipping <PlexGuid:tvdb://7678315> not found
         on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e02/Mission, Once More (2020): Skipping <PlexGuid:tvdb://7681112> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s02e03/To the Heavenly Land (2020): Skipping <PlexGuid:tvdb://7681113> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s02e04/The Sacred Beast Cuadorn (2020): Skipping <PlexGuid:tvdb://7681114> not
         found on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e05/Perfect Sniper (2020): Skipping <PlexGuid:tvdb://7692273> not found on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e06/If It Weren't for You (2020): Skipping <PlexGuid:tvdb://7692274> not found
         on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e07/A Wish Entrusted (2020): Skipping <PlexGuid:tvdb://7692275> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s02e08/To Fly Once More (2020): Skipping <PlexGuid:tvdb://7692276> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s02e09/Seltsam's Deadline (2020): Skipping <PlexGuid:tvdb://7692278> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s02e10/Moment of Choice (2020): Skipping <PlexGuid:tvdb://7692279> not found on
         Trakt
WARNING  Gundam Build Divers Re:Rise/s02e11/Build Divers (2020): Skipping <PlexGuid:tvdb://7692281> not found on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e12/To the Tomorrow I Envision (2020): Skipping <PlexGuid:tvdb://7692282> not
         found on Trakt
WARNING  Gundam Build Divers Re:Rise/s02e13/Re:RISE (2020): Skipping <PlexGuid:tvdb://7705001> not found on Trakt
WARNING  Mobile Suit Gundam/s00e04/Mobile Suit Gundam: Char's Counterattack (1988): Skipping <PlexGuid:tvdb://880381>
         not found on Trakt
WARNING  Mobile Suit Gundam/s00e05/Mobile Suit Gundam F91 (1991): Skipping <PlexGuid:tvdb://880391> not found on Trakt
WARNING  Mobile Suit Gundam Seed Destiny (2004): Skipping <PlexGuid:tvdb://74890> not found on Trakt
WARNING  Mobile Suit Gundam Seed Destiny (2004): Skipping <PlexGuid:imdb://tt0434694> not found on Trakt
WARNING  Mobile Suit Gundam Seed Destiny (2004): Skipping <PlexGuid:tvdb://74890> not found on Trakt
WARNING  Mobile Suit Gundam Seed Destiny (2004): Skipping <PlexGuid:imdb://tt0434694> not found on Trakt

Those last 5 lines seem to be for the show in question that the trace errors mention.

Lastly, it does seem like trakt itself is unaware of the show when searching https://trakt.tv/search?query=gundam+seed+destiny but it seems like https://trakt.tv/shows/mobile-suit-gundam-seed lists season 2 as what I would expect to be considered "gundam seed destiny" which on other platforms is in fact considered a separate show with a separate ID.

For the purpose of the sync, it would be nice to gracefully continue/skip if the show is not found on trakt, which seems to happen for the some other shows as listed in my previous comment showing preceding warnings, but this show causes a failure for some reason.

Please let me know if there is any other information I can provide to help narrow down the issue.

Duplicate of #1785

your inspect is invalid, as it takes arguments as plex web URL or plex id (see readme). you gave plextraktsync guid, that is not yet supported. see readme in your case it's 216124. post to the duplicate issue your details.

messages before crash have no relevance.

Sorry, I tried to provide as much info as I could think might be relevant. I was unaware that #1785 was related as the error messages described are different. I'll grab the plex web url and plex id output of the inspect commands and add it to #1785
Thanks for the quick response.

The error message changed after a PR that you discovered:

and it linked to the duplicate issue :)