microsoft/garnet · error · NotSupportedException

Stream does not support get_Length.

Error message

Stream does not support get_Length.

What it means

PinnedMemoryStream wraps an IStreamBuffer and serves data in chunks; because it does not hold the entire stream in one contiguous buffer, it cannot report a meaningful total Length. Its Length getter throws NotSupportedException by design. The stream is forward-only, chunked, and has no concept of a fixed total size.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/ObjectSerialization/PinnedMemoryStream.cs:70

        {
            if (cancellationToken.IsCancellationRequested)
                return Task.FromCanceled(cancellationToken);

            try
            {
                streamBuffer.FlushAndReset(cancellationToken);
                return Task.CompletedTask;
            }
            catch (Exception ex)
            {
                return Task.FromException(ex);
            }
        }

        /// <summary>The amount of data in the internal streamBuffer. Not supported because we chunk and thus may not have all data.</summary>
        public override long Length
        {
            get => throw new NotSupportedException("Stream does not support get_Length.");
        }

        /// <summary>The current position of the stream seeking; not supported</summary>
        public override long Position
        {
            get => throw new NotSupportedException("Stream does not support get_Position.");
            set => throw new NotSupportedException("Stream does not support set_Position.");
        }

        /// <summary>Copy data from the internal streamBuffer into the buffer; the streamBuffer handles Flush, Reset, and Read more 
        /// (e.g. from disk or network) as needed.</summary>
        /// <param name="buffer">Buffer to copy the bytes into.</param>
        /// <param name="offset">Index in the buffer to start copying to.</param>
        /// <param name="count">Desired number of bytes to copy to the buffer.</param>
        /// <returns>Number of bytes actually read.</returns>
        public override int Read(byte[] buffer, int offset, int count)
        {
            ValidateBufferArguments(buffer, offset, count);

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Do not query Length on PinnedMemoryStream; track byte counts yourself as you write/read.
  2. If a downstream API needs Length, buffer to a MemoryStream first, then forward (note: loses the streaming/pinning benefit).
  3. Serialize to the BinaryWriter passed to DoSerialize and avoid inspecting the underlying stream.

Example fix

// before
public void DoSerialize(BinaryWriter w)
{
    var len = w.BaseStream.Length; // PinnedMemoryStream -> NotSupportedException
    ...
}
// after
public void DoSerialize(BinaryWriter w)
{
    w.Write(_field); // no Length query needed
}
Defensive patterns

Strategy: validation

Validate before calling

if (stream is PinnedMemoryStream pms) throw new NotSupportedException("Do not query Length on PinnedMemoryStream; track bytes manually");
var len = stream.Length;

Type guard

static bool HasLength(Stream s) => s is not PinnedMemoryStream;

Prevention

When it happens

Trigger: Code that receives a PinnedMemoryStream (used by the object-log serializer as the BinaryWriter backing stream) and accesses its .Length property — e.g. a BinaryWriter, serializer, or third-party code querying Length.

Common situations: A custom IHeapObject serializer that checks stream.Length; wrapping PinnedMemoryStream in a component that requires Length (compression, hashing, length-prefixed framing); debug/logging code that reads Length.

Related errors


AI-assisted analysis of microsoft/garnet@951b0fc683 (2026-08-13). Data as JSON: /api/errors/db1970c96b99518e. Report an issue: GitHub.