jellyfin/jellyfin · error · ResourceNotFoundException

MediaSource {mediaSourceId} not found

Error message

MediaSource {mediaSourceId} not found

What it means

Lookup miss in AttachmentExtractor.GetFileSuffixes/ExtractAttachment entry point. The requested mediaSourceId is resolved against the item's playback media sources (case-insensitive Id match) and nothing matches, so no attachment can be addressed. Thrown as ResourceNotFoundException, which the API layer maps to 404.

Source

Thrown at MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs:77

            _pathManager = pathManager;
        }

        /// <inheritdoc />
        public async Task<(MediaAttachment Attachment, Stream Stream)> GetAttachment(BaseItem item, string mediaSourceId, int attachmentStreamIndex, CancellationToken cancellationToken)
        {
            ArgumentNullException.ThrowIfNull(item);

            if (string.IsNullOrWhiteSpace(mediaSourceId))
            {
                throw new ArgumentNullException(nameof(mediaSourceId));
            }

            var mediaSources = await _mediaSourceManager.GetPlaybackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false);
            var mediaSource = mediaSources
                .FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
            if (mediaSource is null)
            {
                throw new ResourceNotFoundException($"MediaSource {mediaSourceId} not found");
            }

            var mediaAttachment = mediaSource.MediaAttachments
                .FirstOrDefault(i => i.Index == attachmentStreamIndex);
            if (mediaAttachment is null)
            {
                throw new ResourceNotFoundException($"MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}");
            }

            if (string.Equals(mediaAttachment.Codec, "mjpeg", StringComparison.OrdinalIgnoreCase))
            {
                throw new ResourceNotFoundException($"Attachment with stream index {attachmentStreamIndex} can't be extracted for MediaSource {mediaSourceId}");
            }

            var attachmentStream = await GetAttachmentStream(mediaSource, mediaAttachment, cancellationToken)
                    .ConfigureAwait(false);

            return (mediaAttachment, attachmentStream);

View on GitHub (pinned to ae8723026d)

Solutions

  1. Have the client re-fetch the item's MediaSources and use a current Id.
  2. Confirm the underlying media file is readable and present.
  3. If the source is dynamic (Live TV), do not call attachment extraction — it has no persistent Id.
Defensive patterns

Strategy: validation

Validate before calling

// Resolve a current media source before attachment calls.
var sources = await _mediaSourceManager.GetPlaybackMediaSources(item, null, true, false, ct);
var src = sources.FirstOrDefault(s => string.Equals(s.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));
if (src is null) return NotFound(); // don't call the extractor

Try / catch

try { await attachmentExtractor.ExtractAttachment(item, mediaSourceId, idx, ct); }
catch (ResourceNotFoundException ex) when (ex.Message.StartsWith("MediaSource "))
{
    logger.LogWarning("Stale or unknown mediaSourceId {Id}.", mediaSourceId);
    return NotFound();
}

Prevention

When it happens

Trigger: _mediaSourceManager.GetPlaybackMediaSources(item, null, true, false, ct) returns a list in which no source has an Id equal to the requested mediaSourceId (OrdinalIgnoreCase).

Common situations: Stale mediaSourceId cached by a client after a library refresh regenerated source IDs; the item genuinely has no media sources (empty/unreadable file); permission or path issue suppressing sources; requesting an attachment for a Live TV stream whose Id is ephemeral.

Related errors


AI-assisted analysis of jellyfin/jellyfin@ae8723026d (2026-08-13). Data as JSON: /api/errors/c04aa536c330b742. Report an issue: GitHub.