Every piece of media tracked by Riven — whether aDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/rivenmedia/riven/llms.txt
Use this file to discover all available pages before exploring further.
Movie, Show, Season, or Episode — carries a last_state field that records exactly where it sits in the processing pipeline. This state machine is the backbone of Riven’s automation: the event loop reads last_state to decide which service should handle an item next, and services write a new last_state when their work succeeds or fails.
The States Enum
States are defined inprogram/media/state.py as a Python Enum:
State Definitions
Unknown
The item’s state cannot be determined — usually because it was just inserted into the database without enough context, or because a service returned an unexpected result. The event loop will attempt to re-process the item from the beginning on the next cycle.
Unreleased
The media has not been released yet. The indexer detected a future release date and will not attempt scraping until the release window arrives. Riven periodically re-checks unreleased items.
Ongoing
Applies to TV shows where new episodes are still airing. A show in Ongoing is decomposed into its constituent seasons and episodes, each of which progresses independently. The show itself returns to Ongoing (or advances to Completed) as episodes finish.
Requested
An item has been received from a content source (Overseerr, Plex Watchlist, Listrr, Mdblist, or Trakt) and is queued for the indexer. This is the entry point for all newly discovered media.
Indexed
Metadata has been fetched from TMDB or TVDB (title, year, genres, episode list, etc.). The item is now ready to be passed to the scraper.
Scraped
At least one suitable torrent was found by the scraper and scored by RTN. The winning infohash is recorded in active_stream. The item is queued for the downloader to send to the debrid provider.
Downloaded
The debrid provider has cached the torrent and reported a download link. The item is queued for the filesystem service to register it in RivenVFS.
Symlinked
The item has been registered in RivenVFS and is accessible on the host filesystem via the FUSE mount. Despite the name, no actual symlinks are created — the term is a legacy of an earlier architecture. The item is now queued for the updater to trigger a library scan.
The
Symlinked state name is preserved for backwards compatibility. It means “the file is available in the virtual filesystem” rather than “a symlink exists on disk.”Completed
The media server (Plex, Jellyfin, or Emby) has confirmed the item is in its library. Post-processing tasks run once at this point, and the item enters a steady resting state. Riven will not re-process it unless explicitly retried.
PartiallyCompleted
One or more child items (seasons or episodes) are Completed but the parent is not fully done yet. This state applies to Show and Season items and drives the scheduler to keep attempting the remaining incomplete children.
Failed
All scraping attempts have been exhausted (controlled by scraping.max_failed_attempts). The event loop will not automatically retry a Failed item. Use the retry API to re-queue it manually.
Paused
The item has been manually paused through the API. Like Failed, the event loop skips paused items completely. Use the unpause endpoint to resume normal processing.
State Transition Flow
The following diagram shows the normal happy-path progression and the branches that lead toOngoing, PartiallyCompleted, Failed, and Paused:
process_event function in program/state_transition.py encodes every transition:
Checking Item States via the API
Filter items by state using thestate query parameter on the items endpoint:
last_state, scraped_times, and other metadata that helps diagnose why an item is stuck.
Retrying Failed Items
To re-queue one or more failed (or otherwise stuck) items, send their IDs to the retry endpoint:scraped_at, scraped_times, and active_stream, then re-emits the items into the event queue starting from the Indexed state.
You can also trigger a bulk retry of the entire library with: