SixLabors/ImageSharp · error · InvalidImageContentException
Unexpected end of stream while reading gif XMP data
Error message
Unexpected end of stream while reading gif XMP data
What it means
Thrown when a GIF XMP application extension block is truncated: ReadXmpData reaches the end of the stream before finding the XMP magic trailer that terminates the payload. SixLabors.ImageSharp throws InvalidImageContentException because the image data itself is malformed/incomplete.
Solutions
- Verify the GIF file is complete and re-download or re-export it from the original source
- Wrap Image.Load in a try-catch for InvalidImageContentException and treat the file as corrupt
- Check the GIF with a validator or hex inspector: the XMP block must end with the 257-byte magic trailer (0xFE followed by 256 bytes including the terminating 0x00)
- If files come from a producer of GIFs, fix that encoder to emit the complete XMP block including the magic trailer
Example fix
// before
var image = Image.Load("animated.gif");
// after
try
{
var image = Image.Load("animated.gif");
}
catch (InvalidImageContentException)
{
// corrupt/truncated GIF (e.g. missing XMP magic trailer)
image = null;
} Defensive patterns
Strategy: try-catch
Validate before calling
// GIF must contain a full XMP block ending in the magic trailer
static bool GifLooksTruncated(string path) =>
new FileInfo(path).Length == 0; // real content validation happens on load Type guard
static bool IsValidImageContentException(Exception ex) => ex is InvalidImageContentException;
Try / catch
try
{
var image = Image.Load(path);
}
catch (InvalidImageContentException ex)
{
// GIF XMP data truncated: file is corrupt, do not retry
HandleCorruptImage(path, ex);
} Prevention
- Validate downloads with checksums before loading GIFs
- Reject zero-length or obviously truncated files early
- Fix producers to write the complete XMP magic trailer
When it happens
Trigger: Calling Image.Load/LoadAsync (or GifDecoder) on a GIF whose XMP application extension data chunk is cut off mid-extension, e.g. a partially downloaded or truncated file where the 0x00 magic trailer never appears.
Common situations: Interrupted downloads or uploads of GIFs; file corruption on disk; a tool or hand-rolled encoder writing an incomplete XMP sub-block; CDN/proxy truncation of large GIF payloads.
Related errors
- The ANI file contains a truncated RIFF list.
- Bad sampling factor
- Gif image does not contain a Logical Screen Descriptor.
- Invalid gif colormap size
- Not enough bytes to read icon header.
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/b4d8a34a9e27e6e3.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Gif/Sections/GifXmpApplicationExtension.cs:36
public int ContentLength => (this.Data.Length > 0) ? this.Data.Length + 269 : 0;
/// <summary>
/// Gets the raw Data.
/// </summary>
public byte[] Data { get; }
/// <summary>
/// Reads the XMP metadata from the specified stream.
/// </summary>
/// <param name="stream">The stream to read from.</param>
/// <param name="allocator">The memory allocator.</param>
/// <returns>The XMP metadata</returns>
public static GifXmpApplicationExtension Read(BufferedReadStream stream, MemoryAllocator allocator)
{
byte[] xmpBytes = ReadXmpData(stream, allocator, out bool terminated);
if (!terminated)
{
throw new InvalidImageContentException("Unexpected end of stream while reading gif XMP data");
}
// Exclude the "magic trailer", see XMP Specification Part 3, 1.1.2 GIF
int xmpLength = xmpBytes.Length - 256; // 257 - unread 0x0
byte[] buffer = [];
if (xmpLength > 0)
{
buffer = new byte[xmpLength];
xmpBytes.AsSpan(0, xmpLength).CopyTo(buffer);
stream.Skip(1); // Skip the terminator.
}
return new GifXmpApplicationExtension(buffer);
}
public int WriteTo(Span<byte> buffer)
{
int bytesWritten = 0;View on GitHub (pinned to 59ce6af6fc)