Skip to content

Live search returns non-resolvable synthetic IDs and can expose internal stream URLs to clients #168

@0oAstro

Description

@0oAstro

Summary

When Gelato live search is enabled, /Users/{userId}/Items?SearchTerm=... can return synthetic Stremio/Gelato GUIDs for search results. Those IDs are not always resolvable by Jellyfin detail/playback endpoints such as /Users/{userId}/Items/{id} or /Items/{id} unless an insert path has already materialized the item.

A related playback issue is that generated MediaSourceInfo entries may mark addon/debrid HTTP URLs as direct-playable and expose them to clients. In self-hosted setups those URLs can be internal Docker/service URLs (for example an internal addon reverse proxy), so remote clients try to direct-play an unreachable URL instead of proxying through Jellyfin.

Repro shape

Environment observed locally:

  • Jellyfin 10.11.x
  • Gelato 0.26.15.1
  • Live search enabled (DisableSearch=false)
  • Stremio/AIOStreams-backed catalogs/search

Steps:

  1. Search via Jellyfin API:
    GET /Users/{userId}/Items?SearchTerm=The%20Phoenician%20Scheme&Recursive=true&Limit=8&Fields=ProviderIds
  2. Gelato intercepts the search and returns a synthetic result ID.
  3. Open details:
    GET /Users/{userId}/Items/{syntheticId}
  4. The detail request can return 404 because the synthetic ID is only in Gelato's search/meta cache and not a canonical Jellyfin item ID.

For already-materialized items, search should prefer the canonical Jellyfin item ID. Example observed with a canonical item already in the library:

  • Search result synthetic ID returned first.
  • Canonical Jellyfin item existed and /Users/{userId}/Items/{canonicalId} worked.
  • /Users/{userId}/Items/{syntheticId} failed.

For remote playback, MediaSourceInfo.Path in API responses can contain an internal addon URL and SupportsDirectPlay=true, which lets clients bypass Jellyfin and time out off-LAN.

Expected behavior

  • Search results should prefer an existing canonical Jellyfin item when provider IDs match, instead of returning a synthetic ID.
  • Synthetic search IDs should be resolvable by item detail/playback insert filters when no canonical item exists yet.
  • Addon/debrid HTTP stream URLs should not be advertised as direct-playable to clients when Jellyfin is expected to proxy them.

Local mitigation tested

A local patch fixed the observed failures by:

  • In SearchActionFilter.ConvertMetasToDtos, calling manager.FindExistingItem(baseItem) and returning the existing item DTO when present.
  • Extending insertable action/user-id detection for detail/playback routes where user id may be an action/route argument instead of only a claim/query param.
  • Marking Gelato stream media sources as not direct-playable and stubbing URLs in DTO/playback responses so clients proxy through Jellyfin.

After patching locally:

  • Live search still returned in ~0.4-1.1s for tested titles.
  • Existing items returned canonical IDs.
  • Live-only search results could be opened and materialized instead of 404ing.
  • Public Jellyfin /Videos/{itemId}/stream.mkv?... returned HTTP 200 and started streaming, while API responses no longer exposed the internal addon URL as a direct-playable source.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions