dotnet/machinelearning · error · EndOfStreamException
Unable to read beyond the end of the stream.
Error message
Unable to read beyond the end of the stream.
What it means
ReadAtLeastCore reads repeatedly until the requested minimum bytes are read; if the stream returns 0 bytes (end of stream) and throwOnEndOfStream is true, it throws EndOfStreamException('Unable to read beyond the end of the stream.'), matching Stream.ReadExactly semantics.
Solutions
- Verify the stream length/remaining bytes >= requested count before calling ReadExactly, or use the ReadAtLeast variant with throwOnEndOfStream:false
- Reset the stream position (stream.Position = 0) if the data was already read
- Check data integrity: the source may be truncated or the format header lies about sizes
Example fix
// before
StreamUtils.ReadExactly(stream, buffer, 0, expectedSize); // throws on short stream
// after
if (stream.Length - stream.Position < expectedSize)
throw new InvalidDataException($"Expected {expectedSize} bytes, only {stream.Length - stream.Position} available");
StreamUtils.ReadExactly(stream, buffer, 0, expectedSize); Defensive patterns
Strategy: try-catch
Validate before calling
bool canReadExactly = stream.CanSeek == false || (stream.Length - stream.Position) >= expectedBytes;
Try / catch
try { StreamUtils.ReadExactly(stream, buffer, 0, expectedBytes); }
catch (EndOfStreamException ex) when (ex.Message.Contains("Unable to read beyond the end"))
{ // handle truncated input: abort, resync format parser, or re-download
throw new InvalidDataException("Stream ended before expected bytes were read", ex); } Prevention
- Check stream.Length - stream.Position before exact reads on seekable streams
- Validate file completeness (checksum/size) before parsing
- Reset stream position if prior code may have consumed the stream
- Treat EndOfStreamException during format parsing as corrupt/truncated input
When it happens
Trigger: Calling ReadExactly for N bytes when the underlying stream contains fewer than N bytes remaining (truncated file, closed network stream, already fully consumed stream).
Common situations: Parsing binary formats whose length header disagrees with actual payload size; truncated/corrupt downloads; reading past the end when the stream position was left at EOF by earlier code; network streams closed mid-transfer.
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
- A quoted field opened on line
- Count must be non-negative and count must not exceed…
- Expected a seekable stream
- Offset must be non-negative. (Parameter 'offset')
- Stream should be non-null and its stream.CanRead property…
AI-assisted analysis of dotnet/machinelearning@7b76e69cf9 (2026-09-11).
Data as JSON: /api/errors/1137287d647cecf6.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.ML.Data/Utilities/StreamUtils.cs:225
}
}
// No argument checking is done here. It is up to the caller.
private static int ReadAtLeastCore(Stream stream, byte[] buffer, int offset, int minimumBytes, bool throwOnEndOfStream)
{
Debug.Assert(minimumBytes <= buffer.Length);
int count = minimumBytes;
int totalRead = 0;
while (totalRead < minimumBytes)
{
int read = stream.Read(buffer, offset, count);
offset += read;
count -= read;
if (read == 0)
{
if (throwOnEndOfStream)
{
throw new EndOfStreamException("Unable to read beyond the end of the stream.");
}
return totalRead;
}
totalRead += read;
}
return totalRead;
}
/// <summary>
/// Reads <paramref name="count"/> number of bytes from the current stream and advances the position within the stream.
/// </summary>
/// <param name="stream"></param>
/// <param name="buffer">
/// An array of bytes. When this method returns, the buffer contains the specified byte array with the values
/// between <paramref name="offset"/> and (<paramref name="offset"/> + <paramref name="count"/> - 1) replacedView on GitHub (pinned to 7b76e69cf9)