dotnet/wpf · error · ArgumentException

can’t seek on baseStream

Error message

can’t seek on baseStream

What it means

SharedStream wraps an underlying stream at a fixed offset/length window, and that requires the base stream to support seeking (CanSeek). Initialize throws ArgumentException "can't seek on baseStream" when handed a non-seekable stream such as a network or pipe stream.

Solutions

  1. Wrap the non-seekable source in a seekable buffer first: copy into MemoryStream (or FileStream) and pass that to SharedStream.
  2. Use File.ReadAllBytes/FileStream when the BAML originates from disk.
  3. For HTTP sources, download the full response to memory before constructing the stream.
  4. If you own the API boundary, pre-check baseStream.CanSeek and fail fast with a clear message.

Example fix

// before
using var resp = await http.SendAsync(req);
var shared = new SharedStream(resp.Content.ReadAsStream(), 0, length); // not seekable
// after
using var resp = await http.SendAsync(req);
using var ms = new MemoryStream();
await resp.Content.CopyToAsync(ms);
ms.Position = 0;
var shared = new SharedStream(ms, 0, ms.Length);
Defensive patterns

Strategy: type-guard

Validate before calling

// Pre-check seekability before constructing SharedStream
if (!source.CanSeek)
{
    var buffered = new MemoryStream();
    source.CopyTo(buffered);
    buffered.Position = 0;
    source = buffered;
}

Type guard

static bool IsSeekable(Stream s) => s is { CanSeek: true };

Try / catch

try
{
    var shared = new SharedStream(source, offset, length);
}
catch (ArgumentException ex) when (ex.Message.Contains("can’t seek"))
{
    // buffer the source into a seekable stream and retry
    throw new InvalidOperationException("Buffer the non-seekable stream into MemoryStream first.", ex);
}

Prevention

When it happens

Trigger: Constructing SharedStream (via Initialize) with a Stream whose CanSeek is false — e.g. NetworkStream, stdout/stdin streams, or an unbuffered deflate/http response stream.

Common situations: Loading BAML from a web response or network stream without buffering; passing Console.OpenStandardInput/Output; wrapping a stream obtained from a streaming HTTP download of a XAP/resource.

Understand the failure class

Background: "is not a compatible type" / "cannot merge" errors: when a value's type doesn't match what the library requires — this error's family across 65 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/700b72bb4c31c384. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/Baml2006/SharedStream.cs:47

        /// <summary>
        /// Constructor that limits the bytes that can be written to or read form
        /// </summary>
        /// <param name="baseStream"></param>
        /// <param name="offset"></param>
        /// <param name="length"></param>
        public SharedStream(Stream baseStream, long offset, long length)
        {
            ArgumentNullException.ThrowIfNull(baseStream);

            Initialize(baseStream, offset, length);
        }

        private void Initialize(Stream baseStream, long offset, long length)
        {
            if (!baseStream.CanSeek)
            {
                throw new ArgumentException("can\u2019t seek on baseStream");
            }

            ArgumentOutOfRangeException.ThrowIfNegative(offset);

            ArgumentOutOfRangeException.ThrowIfNegative(length);

            SharedStream subStream = baseStream as SharedStream;
            if (subStream != null)
            {
                _baseStream = subStream.BaseStream;
                _offset = offset + subStream._offset;
                _length = length;
                _refCount = subStream._refCount;
                _refCount.Value++;
            }
            else
            {
                _baseStream = baseStream;

View on GitHub (pinned to 81131a70a4)