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
- Have the client re-fetch the item's MediaSources and use a current Id.
- Confirm the underlying media file is readable and present.
- 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
- Have clients always re-fetch MediaSources before requesting attachments.
- Do not cache mediaSourceId across library refreshes.
- Avoid attachment extraction on dynamic/Live TV sources.
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
- MediaSource {mediaSourceId} has no attachment with stream in
- Attachment with stream index {attachmentStreamIndex} can't b
- MediaSource {mediaSource.Id} has no attachment cache (non-GU
- ffprobe failed - streams and format are both null.
- ffmpeg image extraction timed out for {0} after {1}ms
AI-assisted analysis of jellyfin/jellyfin@ae8723026d (2026-08-13).
Data as JSON: /api/errors/c04aa536c330b742.
Report an issue: GitHub.