SixLabors/ImageSharp · error · InvalidImageContentException
Unexpected end of stream while reading gif application…
Error message
Unexpected end of stream while reading gif application extension
What it means
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.
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
Example fix
// before
var image = Image.Load(stream);
// after
try { var image = Image.Load(stream); }
catch (InvalidImageContentException ex) { logger.LogWarning(ex, "Truncated GIF"); image = CreatePlaceholder(); } Defensive patterns
Strategy: try-catch
Validate before calling
// Verify the stream is large enough to contain a Netscape extension
if (stream.CanSeek && stream.Length < 14) throw new InvalidDataException("Truncated GIF");
Try / catch
try { return Image.Load(stream); }
catch (InvalidImageContentException ex) when (ex.Message.Contains("gif application extension")) { return RepairOrPlaceholder(stream); } Prevention
- 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
When it happens
Trigger: 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.
Common situations: Interrupted downloads, files cut off mid-transfer, GIFs generated by buggy encoders that omit the extension terminator.
Related errors
- Gif image does not contain a Logical Screen Descriptor.
- Unable to read Gif image data
- Invalid gif colormap size
- Input stream does not have enough bytes to parse declared…
- The ANI file does not contain any frame resources.
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/8e07ee528ce1c76c.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Gif/GifDecoderCore.cs:452
}
/// <summary>
/// Reads the GIF NETSCAPE looping application extension.
/// </summary>
/// <param name="stream">The <see cref="BufferedReadStream"/> containing image data.</param>
private void ReadNetscapeApplicationExtension(BufferedReadStream stream) =>
this.ExecuteAncillarySegmentAction(() => this.ReadNetscapeApplicationExtensionData(stream));
/// <summary>
/// Reads the GIF NETSCAPE looping application extension data.
/// </summary>
/// <param name="stream">The <see cref="BufferedReadStream"/> containing image data.</param>
private void ReadNetscapeApplicationExtensionData(BufferedReadStream stream)
{
int bytesRead = stream.Read(this.buffer, 0, GifConstants.NetscapeLoopingSubBlockSize);
if (bytesRead != GifConstants.NetscapeLoopingSubBlockSize)
{
throw new InvalidImageContentException("Unexpected end of stream while reading gif application extension");
}
this.gifMetadata!.RepeatCount = GifNetscapeLoopingApplicationExtension.Parse(this.buffer[1..]).RepeatCount;
int terminator = stream.ReadByte();
if (terminator == -1)
{
throw new InvalidImageContentException("Unexpected end of stream while reading gif application extension");
}
}
/// <summary>
/// Skips over a block or reads its terminator.
/// </summary>
/// <param name="stream">The <see cref="BufferedReadStream"/> containing image data.</param>
/// <param name="blockSize">The length of the block to skip.</param>
private static void SkipBlock(BufferedReadStream stream, int blockSize = 0)
{View on GitHub (pinned to 59ce6af6fc)