{"record":{"id":"295b5341a5b52e1f","repo":"jellyfin/jellyfin","slug":"attachment-with-stream-index-attachmentstreaminde","errorCode":null,"errorMessage":"Attachment with stream index {attachmentStreamIndex} can't be extracted for MediaSource {mediaSourceId}","messagePattern":"Attachment with stream index (.+?) can't be extracted for MediaSource (.+?)","errorType":"http","errorClass":"ResourceNotFoundException","httpStatus":404,"severity":"error","filePath":"MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs","lineNumber":89,"sourceCode":"\n            var mediaSources = await _mediaSourceManager.GetPlaybackMediaSources(item, null, true, false, cancellationToken).ConfigureAwait(false);\n            var mediaSource = mediaSources\n                .FirstOrDefault(i => string.Equals(i.Id, mediaSourceId, StringComparison.OrdinalIgnoreCase));\n            if (mediaSource is null)\n            {\n                throw new ResourceNotFoundException($\"MediaSource {mediaSourceId} not found\");\n            }\n\n            var mediaAttachment = mediaSource.MediaAttachments\n                .FirstOrDefault(i => i.Index == attachmentStreamIndex);\n            if (mediaAttachment is null)\n            {\n                throw new ResourceNotFoundException($\"MediaSource {mediaSourceId} has no attachment with stream index {attachmentStreamIndex}\");\n            }\n\n            if (string.Equals(mediaAttachment.Codec, \"mjpeg\", StringComparison.OrdinalIgnoreCase))\n            {\n                throw new ResourceNotFoundException($\"Attachment with stream index {attachmentStreamIndex} can't be extracted for MediaSource {mediaSourceId}\");\n            }\n\n            var attachmentStream = await GetAttachmentStream(mediaSource, mediaAttachment, cancellationToken)\n                    .ConfigureAwait(false);\n\n            return (mediaAttachment, attachmentStream);\n        }\n\n        /// <inheritdoc />\n        public async Task ExtractAllAttachments(\n            string inputFile,\n            MediaSourceInfo mediaSource,\n            CancellationToken cancellationToken)\n        {\n            var shouldExtractOneByOne = mediaSource.MediaAttachments.Any(a => !string.IsNullOrEmpty(a.FileName)\n                                                                              && !string.Equals(PathHelper.GetSafeLeafFileName(a.FileName), a.FileName, StringComparison.Ordinal));\n            if (shouldExtractOneByOne && !inputFile.EndsWith(\".mks\", StringComparison.OrdinalIgnoreCase))\n            {","sourceCodeStart":71,"sourceCodeEnd":107,"githubUrl":"https://github.com/jellyfin/jellyfin/blob/ae8723026d97b6d0f926638803edef338919b794/MediaBrowser.MediaEncoding/Attachments/AttachmentExtractor.cs#L71-L107","documentation":"An intentional extraction refusal: the matched attachment's Codec is 'mjpeg' (case-insensitive). MJPEG 'attachments' are embedded cover/cover-image frames, not the font files attachment extraction is built for, so ffmpeg cannot pull them out as a normal attachment. Treated as ResourceNotFoundException (404) so clients treat it as 'not extractable'.","triggerScenarios":"mediaAttachment is found and string.Equals(mediaAttachment.Codec, \"mjpeg\", StringComparison.OrdinalIgnoreCase) is true.","commonSituations":"A media file stores its cover art as an MJPEG attachment; the client blindly tries to extract every listed attachment; metadata reports an attachment whose codec is mjpeg.","solutions":["Skip attachments whose codec is mjpeg when listing extractable attachments.","Use the cover-art/image endpoint instead of the attachment endpoint for embedded MJPEG art.","Filter client-side before issuing the extraction request."],"exampleFix":"// before\nvar attachment = mediaSource.MediaAttachments.First(a => a.Index == idx);\n\n// after: skip non-extractable MJPEG art\nvar attachment = mediaSource.MediaAttachments\n    .FirstOrDefault(a => a.Index == idx\n        && !string.Equals(a.Codec, \"mjpeg\", StringComparison.OrdinalIgnoreCase));","handlingStrategy":"validation","validationCode":"// Skip MJPEG attachments (embedded cover art) before extracting.\nif (string.Equals(attach.Codec, \"mjpeg\", StringComparison.OrdinalIgnoreCase))\n{\n    return NotFound(\"MJPEG attachments are not extractable; use the cover-art endpoint.\");\n}","typeGuard":"static bool IsExtractableAttachment(MediaAttachment a) =>\n    !string.Equals(a.Codec, \"mjpeg\", StringComparison.OrdinalIgnoreCase);","tryCatchPattern":"try { /* extract */ }\ncatch (ResourceNotFoundException ex) when (ex.Message.Contains(\"can't be extracted\"))\n{\n    return NotFound(\"Attachment is MJPEG cover art and cannot be extracted.\");\n}","preventionTips":["Filter MJPEG attachments out of any 'extract all attachments' loop.","Use the image/cover-art endpoint for embedded MJPEG art.","Document that MJPEG attachments are intentionally non-extractable."],"tags":["attachment","media-encoding","codec","mjpeg"],"backgroundTag":null,"analyzedSha":"ae8723026d97b6d0f926638803edef338919b794","analyzedAt":"2026-08-13T10:43:30.013Z","schemaVersion":2},"datasetVersion":"2026-08-13T14:17:21.547Z"}