stride3d/stride · error · IOException
Can't read beyond end of stream.
Error message
Can't read beyond end of stream.
What it means
AcquireNextChunk validates chunk metadata: compressedLength must not exceed originalLength, since LZ4 block compression never expands data. A chunk claiming a compressed size larger than its original size indicates a corrupted or malformed stream, so the library throws IOException.
Solutions
- Regenerate/re-download the compressed file; treat it as corrupted
- Verify the chunk header layout matches the LZ4Stream format (flags, originalLength, compressedLength order)
- Add a checksum/integrity check on stored compressed files
- Ensure no seeking/offset misalignment when wrapping the inner stream
Example fix
// before
using var s = new LZ4Stream(File.OpenRead(path)); // throws on corrupt header
// after
if (!HasValidChecksum(path)) throw new InvalidDataException("corrupt lz4 file");
using var s = new LZ4Stream(File.OpenRead(path)); Defensive patterns
Strategy: validation
Validate before calling
// before opening: verify integrity of stored file
if (!VerifyChecksum(path)) throw new InvalidDataException("LZ4 asset failed integrity check"); Try / catch
try { using var s = new LZ4Stream(File.OpenRead(path)); ... }
catch (IOException ex) when (ex.Message.Contains("beyond end of stream")) { // corrupted stream: redownload/regenerate
} Prevention
- Store checksums alongside compressed assets and verify before reading
- Avoid manual edits or byte-level manipulation of LZ4 files
- Handle storage/disk errors that can corrupt files
When it happens
Trigger: Reading an LZ4Stream whose chunk header was corrupted (bit flips, bad write) so compressedLength > originalLength; reading a file produced by an incompatible writer.
Common situations: Disk corruption or partial overwrite of compressed assets; hand-rolled producers writing chunk headers incorrectly; concatenating streams incorrectly so the reader lands on garbage bytes.
Understand the failure class
Background: Checksum mismatch errors: "checksum verification failed", "digest mismatch", "expected vs actual checksum" — what they mean and how to fix them — this error's family across 41 libraries.
Related errors
- Unexpected end of stream
- Chunks with multiple passes are not supported.
- File doesn't appear to be a valid package
- Count cannot be less than zero
- Operation 'SetPosition' is not supported
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/dc8379ec1d4a1a15.
Report an issue: GitHub.
Appendix: source
Thrown at sources/core/Stride.Core.Serialization/Serialization/LZ4/LZ4Stream.cs:278
innerStreamPosition += compressedLength;
bufferOffset = 0;
}
/// <summary>Reads the next chunk from stream.</summary>
/// <returns><c>true</c> if next has been read, or <c>false</c> if it is legitimate end of file.</returns>
/// <exception cref="IOException">The end of the stream was unexpectedly reached.</exception>
private bool AcquireNextChunk()
{
do
{
if (!TryReadVarInt(out var varint)) return false;
var flags = (ChunkFlags)varint;
var isCompressed = (flags & ChunkFlags.Compressed) != 0;
var originalLength = (int)ReadVarInt();
var compressedLength = isCompressed ? (int)ReadVarInt() : originalLength;
if (compressedLength > originalLength) throw new IOException("Can't read beyond end of stream."); // corrupted
if (compressedDataBuffer == null || compressedDataBuffer.Length < compressedLength)
compressedDataBuffer = new byte[compressedLength];
var chunk = ReadBlock(compressedDataBuffer, 0, compressedLength);
if (chunk != compressedLength) throw new IOException("Can't read beyond end of stream."); // currupted
if (!isCompressed)
{
// swap the buffers
(compressedDataBuffer, dataBuffer) = (dataBuffer, compressedDataBuffer);
bufferLength = compressedLength;
}
else
{
if (dataBuffer == null || dataBuffer.Length < originalLength)
dataBuffer = new byte[originalLength];
var passes = (int)flags >> 2;View on GitHub (pinned to 96fad776d2)