jellyfin/jellyfin · error · ResourceNotFoundException

MediaSource {mediaSourceId} has no attachment with stream in

Error message

MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}

What it means

The media source was found, but it has no MediaAttachment entry whose Index equals the requested attachmentStreamIndex. ResourceNotFoundException maps to 404. This is distinct from [127] (no source at all): the source exists, it just lacks that attachment slot.

Source

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

            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);
        }

        /// <inheritdoc />
        public async Task ExtractAllAttachments(
            string inputFile,
            MediaSourceInfo mediaSource,
            CancellationToken cancellationToken)

View on GitHub (pinned to ae8723026d)

Solutions

  1. Refresh metadata for the item so MediaAttachments is rebuilt from the current file.
  2. Have the client enumerate the available attachment indices from MediaSources before requesting one.
  3. Confirm the file actually contains embedded attachments (ffprobe -attach).
Defensive patterns

Strategy: validation

Validate before calling

// Verify the requested attachment index exists first.
var attach = mediaSource.MediaAttachments.FirstOrDefault(a => a.Index == attachmentStreamIndex);
if (attach is null) return NotFound($"No attachment {attachmentStreamIndex}");

Type guard

static bool HasAttachment(MediaSourceInfo src, int idx) =>
    src.MediaAttachments?.Any(a => a.Index == idx) == true;

Try / catch

try { /* extract */ }
catch (ResourceNotFoundException ex) when (ex.Message.Contains("no attachment"))
{
    logger.LogInformation("Attachment {Idx} absent on {Id}; refreshing metadata.", idx, mediaSourceId);
    return NotFound();
}

Prevention

When it happens

Trigger: mediaSource is non-null, but mediaSource.MediaAttachments.FirstOrDefault(i => i.Index == attachmentStreamIndex) returns null.

Common situations: Client requests an attachment index that was present in an older version of the file; the file changed since metadata was cached (attachments renumbered); the file has no embedded attachments at all but the client assumed one; metadata cache stale after remuxing.

Related errors


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