dotnet/wpf · error · System.IO.EndOfStreamException
SR.EndOfStreamReached
Error message
SR.EndOfStreamReached
What it means
BitStream.ReadByte attempts to read 1-8 bits from the underlying stream and throws EndOfStreamException(SR.EndOfStreamReached) when the stream is already exhausted (EndOfStream is true). The library signals that the caller asked for more bit data than the stream contains rather than returning a partial/zero value.
Solutions
- Check BitStream.EndOfStream before each ReadByte call and stop decoding when true.
- Validate that the ISF/stream data is complete (correct total length) before decoding.
- Catch EndOfStreamException around ISF decoding and treat the input as truncated/corrupt.
- Fix the loop bounds so the number of reads matches the actual byte/bit length of the stream.
Example fix
// before
while (i < packetCount)
packets[i] = bitStream.ReadByte(8); // may overrun a short stream
// after
while (i < packetCount && !bitStream.EndOfStream)
packets[i] = bitStream.ReadByte(8);
if (i < packetCount)
throw new InvalidDataException("ISF stream truncated before all packets were read"); Defensive patterns
Strategy: validation
Validate before calling
if (bitStream.EndOfStream)
return null; // or stop decoding
byte v = bitStream.ReadByte(countOfBits); Type guard
static bool CanRead(BitStream s) => !s.EndOfStream;
Try / catch
try
{
byte v = bitStream.ReadByte(8);
}
catch (EndOfStreamException)
{
// stream exhausted: treat ISF data as truncated
throw new InvalidDataException("ISF stream ended before all data was read");
} Prevention
- Check EndOfStream before every read in decode loops.
- Verify total stream length matches expected packet counts before decoding.
- Stop iterating when EndOfStream becomes true rather than trusting declared counts.
- Treat EndOfStreamException during ISF decode as data corruption, not a retryable state.
When it happens
Trigger: Calling ReadByte after all bytes in the stream have been consumed. Callers include GetDataFromReader, Uncompress, LoadPackets, and the indexer (b); truncated or mis-lengthed ISF/stroke data makes decoding overrun the buffer.
Common situations: Parsing a truncated or corrupted ISF file (incomplete download, bad save); a decoder loop that iterates a packet count larger than the data present.
Related errors
- SR.CountOfBitsGreatThanRemainingBits
- Read different size from stream then expected
- Read different size from stream then expected
- SR.InvalidStringFormat
- String format is not valid.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/786d98b92b27ecae.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Ink/BitStream.cs:230
{
byte b = ReadByte(1);
return ((b & 1) == 1);
}
/// <summary>
/// Read a specified number of bits from the stream into a single byte
/// </summary>
/// <param name="countOfBits">The number of bits to unpack</param>
/// <returns>A single byte that contains up to 8 packed bits</returns>
/// <remarks>For example, if 2 bits are read from the stream, then a full byte
/// will be created with the least significant bits set to the 2 unpacked bits
/// from the stream</remarks>
internal byte ReadByte(int countOfBits)
{
// if the end of the stream has been reached, then throw an exception
if (EndOfStream)
{
throw new System.IO.EndOfStreamException(SR.EndOfStreamReached);
}
// we only support 1-8 bits currently, not multiple bytes, and not 0 bits
if (countOfBits > Native.BitsPerByte || countOfBits <= 0)
{
throw new ArgumentOutOfRangeException(nameof(countOfBits), countOfBits, SR.CountOfBitsOutOfRange);
}
if (countOfBits > _bufferLengthInBits)
{
throw new ArgumentOutOfRangeException(nameof(countOfBits), countOfBits, SR.CountOfBitsGreatThanRemainingBits);
}
_bufferLengthInBits -= (uint)countOfBits;
// initialize return byte to 0 before reading from the cache
byte returnByte = 0;
View on GitHub (pinned to 81131a70a4)