{"record":{"id":"8e07ee528ce1c76c","repo":"SixLabors/ImageSharp","slug":"unexpected-end-of-stream-while-reading-gif-application","errorCode":null,"errorMessage":"Unexpected end of stream while reading gif application extension","messagePattern":"Unexpected end of stream while reading gif application extension","errorType":"exception","errorClass":"InvalidImageContentException","httpStatus":null,"severity":"error","filePath":"src/ImageSharp/Formats/Gif/GifDecoderCore.cs","lineNumber":452,"sourceCode":"    }\n\n    /// <summary>\n    /// Reads the GIF NETSCAPE looping application extension.\n    /// </summary>\n    /// <param name=\"stream\">The <see cref=\"BufferedReadStream\"/> containing image data.</param>\n    private void ReadNetscapeApplicationExtension(BufferedReadStream stream) =>\n        this.ExecuteAncillarySegmentAction(() => this.ReadNetscapeApplicationExtensionData(stream));\n\n    /// <summary>\n    /// Reads the GIF NETSCAPE looping application extension data.\n    /// </summary>\n    /// <param name=\"stream\">The <see cref=\"BufferedReadStream\"/> containing image data.</param>\n    private void ReadNetscapeApplicationExtensionData(BufferedReadStream stream)\n    {\n        int bytesRead = stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize);\n        if (bytesRead != GifConstants.NetscapeLoopingSubBlockSize)\n        {\n            throw new InvalidImageContentException(\"Unexpected end of stream while reading gif application extension\");\n        }\n\n        this.gifMetadata!.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer[1..]).RepeatCount;\n\n        int terminator = stream.ReadByte();\n        if (terminator == -1)\n        {\n            throw new InvalidImageContentException(\"Unexpected end of stream while reading gif application extension\");\n        }\n    }\n\n    /// <summary>\n    /// Skips over a block or reads its terminator.\n    /// </summary>\n    /// <param name=\"stream\">The <see cref=\"BufferedReadStream\"/> containing image data.</param>\n    /// <param name=\"blockSize\">The length of the block to skip.</param>\n    private static void SkipBlock(BufferedReadStream stream, int blockSize = 0)\n    {","sourceCodeStart":434,"sourceCodeEnd":470,"githubUrl":"https://github.com/SixLabors/ImageSharp/blob/59ce6af6fc29027cda277ef62d4d1694a8acce91/src/ImageSharp/Formats/Gif/GifDecoderCore.cs#L434-L470","documentation":"Thrown when the GIF stream ends in the middle of the Netscape application extension's data sub-block. The decoder expects the full NetscapeLoopingSubBlockSize bytes followed by a block terminator; fewer bytes means truncated or corrupt input. Raised as InvalidImageContentException.","triggerScenarios":"Image.Load/Decode on a GIF where the Netscape looping extension (0x21 0xFF 0x0B) sub-block read returns fewer than the expected bytes — i.e. the stream ends inside the extension.","commonSituations":"Interrupted downloads, files cut off mid-transfer, GIFs generated by buggy encoders that omit the extension terminator.","solutions":["Re-download or re-export the GIF so the file is complete","Verify file size against the server-provided content length before decoding","Strip the broken Netscape extension with a GIF tool (e.g. gifsicle -b) to salvage the animation","Wrap decode in try-catch and fall back to a placeholder image"],"exampleFix":"// before\nvar image = Image.Load(stream);\n// after\ntry { var image = Image.Load(stream); }\ncatch (InvalidImageContentException ex) { logger.LogWarning(ex, \"Truncated GIF\"); image = CreatePlaceholder(); }","handlingStrategy":"try-catch","validationCode":"// Verify the stream is large enough to contain a Netscape extension\nif (stream.CanSeek && stream.Length < 14) throw new InvalidDataException(\"Truncated GIF\");\n","typeGuard":null,"tryCatchPattern":"try { return Image.Load(stream); }\ncatch (InvalidImageContentException ex) when (ex.Message.Contains(\"gif application extension\")) { return RepairOrPlaceholder(stream); }","preventionTips":["Compare downloaded file size to expected content length","Serve images only after transfer completes (no partial reads)","Re-encode salvaged GIFs with gifsicle/magick","Log and quarantine truncated uploads at ingest"],"tags":["gif","decoder","truncated","stream"],"backgroundTag":"unexpected-response-shape","analyzedSha":"59ce6af6fc29027cda277ef62d4d1694a8acce91","analyzedAt":"2026-09-13T18:34:59.331Z","contentChangedAt":"2026-09-13T18:34:59.331Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}