microsoft/garnet · error · InvalidOperationException

Read is not supported for DiskStreamWriteBuffer

Error message

Read is not supported for DiskStreamWriteBuffer

What it means

DiskStreamWriteBuffer is write-only; its Read implementation throws InvalidOperationException. It exists to serialize objects into the object log and holds a pinned memory stream for writing only. Reading from it is a misuse — the caller invoked a read-side operation on a write-side buffer.

Source

Thrown at libs/storage/Tsavorite/cs/src/core/Allocator/ObjectSerialization/ObjectLogWriter.cs:333

            // If we haven't yet instantiated the serializer do so now.
            if (valueObjectSerializer is null)
            {
                pinnedMemoryStream = new(this);
                valueObjectSerializer = storeFunctions.CreateValueObjectSerializer();
                valueObjectSerializer.BeginSerialize(pinnedMemoryStream);
            }

            valueObjectSerializer.Serialize(valueObject);
            OnSerializeComplete(valueObject);
        }

        void OnSerializeComplete(IHeapObject valueObject)
        {
            inSerialize = false;
        }

        /// <inheritdoc/>
        public int Read(Span<byte> destinationSpan, CancellationToken cancellationToken = default) => throw new InvalidOperationException("Read is not supported for DiskStreamWriteBuffer");

        /// <inheritdoc/>
        public void Dispose()
        {
            var localMemoryStream = Interlocked.Exchange(ref pinnedMemoryStream, null);
            if (localMemoryStream is not null)
            {
                // End serialization before disposing the pinned memory stream as it may try to flush final data which would use the pinnedMemoryStream.
                valueObjectSerializer?.EndSerialize();
                localMemoryStream.Dispose();
            }
        }
    }
}

View on GitHub (pinned to 951b0fc683)

Solutions

  1. Check the buffer type or a CanRead flag before calling Read.
  2. Use distinct pools/types for read vs write buffers so a reader never gets a DiskStreamWriteBuffer.
  3. Ensure the deserialization path receives a DiskStreamReadBuffer, not a write buffer.

Example fix

// before
int n = buffer.Read(dest, cancellationToken);
// after
if (buffer is DiskStreamWriteBuffer)
    throw new InvalidOperationException("Cannot read from a write buffer");
int n = buffer.Read(dest, cancellationToken);
Defensive patterns

Strategy: type-guard

Validate before calling

if (buffer is DiskStreamWriteBuffer) throw new InvalidOperationException("Cannot Read from a write buffer");
int n = buffer.Read(dest, cancellationToken);

Type guard

static bool CanRead(IStreamBuffer b) => b is not DiskStreamWriteBuffer;

Prevention

When it happens

Trigger: Calling Read(Span<byte>) on an IStreamBuffer that is actually a DiskStreamWriteBuffer — e.g. deserialization code that received a write buffer from a shared pool or a misrouted buffer reference.

Common situations: Generic buffer-pool code calling Read on any returned buffer; a refactor routing a write buffer into a read/deserialize path; shared IStreamBuffer handling not distinguishing buffer direction.

Related errors


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