SixLabors/ImageSharp · error · InvalidImageContentException
Reached EOF while reading the header.
Error message
Reached EOF while reading the header.
What it means
Thrown by PbmDecoderCore.ProcessHeader when the stream ends before a complete PNM header (magic, width, height, and for non-mono formats the max pixel value) has been read. The decoder needs the entire header before allocating the pixel buffer; premature EOF means the file is truncated or not a PNM image. Implemented via the local ThrowPrematureEof helper in PbmDecoderCore.cs:186.
Solutions
- Verify the source file/stream is fully written and complete (compare file size against the producer's expected output).
- Re-download or re-export the image; the header bytes are unrecoverable.
- For streams, reset the stream position to 0 before passing it to Image.Identify/Image.Load.
- Check that the writer producing the file finished and disposed/flushed before the decoder reads it.
Example fix
// before
using var stream = File.OpenRead("partial.pgm");
using var image = Image.Load(stream);
// after
using var stream = File.OpenRead("partial.pgm");
if (stream.Length < 10) // smallest sane PNM header is longer than this
{
throw new IOException("PNM file is truncated; re-obtain the file.");
}
stream.Position = 0;
using var image = Image.Load(stream); Defensive patterns
Strategy: validation
Validate before calling
// Ensure the stream holds at least a minimal complete PNM header before decoding
if (!stream.CanSeek || stream.Length < 15)
throw new InvalidDataException("Source too short to contain a PNM header");
stream.Position = 0; Type guard
static bool HasMinimalPnmHeader(Stream s)
{
if (!s.CanSeek || s.Length < 15) return false;
Span<byte> buf = stackalloc byte[2];
s.Read(buf);
s.Position = 0;
return buf[0] == (byte)'P' && buf[1] is >= (byte)'1' and <= (byte)'7';
} Try / catch
try
{
using var image = Image.Load(stream);
}
catch (InvalidImageContentException ex) when (ex.Message.Contains("EOF while reading the header"))
{
throw new IOException("PNM source is truncated; re-obtain the file.", ex);
} Prevention
- Always flush/close writers before another process reads the PNM file.
- Reset stream Position to 0 before decoding streams that were just read or written.
- Check file sizes against producer expectations when receiving files over the network.
- Use Image.Identify on suspicious inputs before full decode.
When it happens
Trigger: Image.Identify or Image.Load on a PNM stream that ends mid-header — e.g. a 0-byte or partially-written file, a stream that was not rewound, or a network source cut off after only the magic bytes.
Common situations: Truncated uploads/downloads, reading from a stream positioned after data was consumed, writing PNM files without flushing/closing the writer, or trying to decode a PNM still being produced by another process.
Understand the failure class
Background: "failed to read file", EACCES, ENOENT and "could not read <path>" errors: when a program can't read a file from disk — this error's family across 49 libraries.
Related errors
- The ANI file contains a truncated RIFF list.
- The ANI file contains a truncated ICO or CUR resource.
- Invalid max pixel value.
- The ANI sequence references a missing frame resource.
- The ANI file does not contain any decodable animation steps.
AI-assisted analysis of SixLabors/ImageSharp@59ce6af6fc (2026-09-13).
Data as JSON: /api/errors/d55745fc3d0bff1e.
Report an issue: GitHub.
Appendix: source
Thrown at src/ImageSharp/Formats/Pbm/PbmDecoderCore.cs:186
}
stream.SkipWhitespaceAndComments();
}
else
{
this.componentType = PbmComponentType.Bit;
}
this.pixelSize = new Size(width, height);
this.Dimensions = this.pixelSize;
this.metadata = new ImageMetadata();
PbmMetadata meta = this.metadata.GetPbmMetadata();
meta.Encoding = this.encoding;
meta.ColorType = this.colorType;
meta.ComponentType = this.componentType;
[DoesNotReturn]
static void ThrowPrematureEof() => throw new InvalidImageContentException("Reached EOF while reading the header.");
}
private void ProcessPixels<TPixel>(BufferedReadStream stream, Buffer2D<TPixel> pixels)
where TPixel : unmanaged, IPixel<TPixel>
{
if (this.encoding == PbmEncoding.Binary)
{
BinaryDecoder.Process(this.configuration, pixels, stream, this.colorType, this.componentType);
}
else
{
PlainDecoder.Process(this.configuration, pixels, stream, this.colorType, this.componentType);
}
}
private void ProcessUpscaling<TPixel>(Image<TPixel> image)
where TPixel : unmanaged, IPixel<TPixel>
{View on GitHub (pinned to 59ce6af6fc)