AvaloniaUI/Avalonia · error · ArgumentException

Stream is not readable

Error message

Stream is not readable

What it means

UnmanagedFontMemory.LoadFromStream copies a font stream into native memory for the rasterizer to access via raw pointer. It refuses to read a stream whose CanRead is false, because it would allocate a buffer and then fail to fill it. This is a precondition check before any allocation.

Source

Thrown at src/Avalonia.Base/Media/Fonts/UnmanagedFontMemory.cs:167

            {
                // Release upgradeable read lock
                _lock.ExitUpgradeableReadLock();
            }
        }

        /// <summary>
        /// Loads font data from the specified stream into unmanaged memory.
        /// </summary>
        public static UnmanagedFontMemory LoadFromStream(Stream stream)
        {
            if (stream is null)
            {
                throw new ArgumentNullException(nameof(stream));
            }

            if (!stream.CanRead)
            {
                throw new ArgumentException("Stream is not readable", nameof(stream));
            }

            if (stream.CanSeek)
            {
                var length = checked((int)stream.Length);
                var ptr = Marshal.AllocHGlobal(length);
                var buffer = ArrayPool<byte>.Shared.Rent(8192);

                try
                {
                    var remaining = length;
                    var offset = 0;

                    while (remaining > 0)
                    {
                        var toRead = Math.Min(buffer.Length, remaining);
                        var read = stream.Read(buffer, 0, toRead);

View on GitHub (pinned to 11c5427268)

Solutions

  1. Check stream.CanRead before calling LoadFromStream and surface a clear error if false.
  2. Open the source file with FileAccess.Read (not Write or ReadWrite-with-closed-handle).
  3. For MemoryStream, ensure it was constructed from a readable source and not disposed.
  4. Re-open the source as a fresh read-only stream rather than reusing a write/transform stream.

Example fix

// before
var mem = UnmanagedFontMemory.LoadFromStream(_writeOnlyStream);

// after
if (stream is null) throw new ArgumentNullException(nameof(stream));
if (!stream.CanRead)
    throw new ArgumentException("Font stream must be readable; reopen the source with FileAccess.Read.", nameof(stream));
var mem = UnmanagedFontMemory.LoadFromStream(stream);
Defensive patterns

Strategy: validation

Validate before calling

static Stream EnsureReadable(Stream s)
{
    if (s is null) throw new ArgumentNullException(nameof(s));
    if (!s.CanRead) throw new ArgumentException("Stream must be readable.", nameof(s));
    if (s.CanSeek && s.Position != 0) s.Position = 0;
    return s;
}

Type guard

static bool IsReadable(Stream s) => s is not null && s.CanRead;

Prevention

When it happens

Trigger: Passing a FileStream opened with FileAccess.Write; passing a MemoryStream whose CanRead was overridden to false; passing a stream that was already disposed (some streams report CanRead=false after disposal); passing a CryptoStream in write-only mode.

Common situations: Reusing a stream after positioning at the end and disposing inadvertently; loading a font from a NetworkStream that the underlying client has closed; wrapping a stream in a write-only adapter for serialization and then reusing it for font loading.

Related errors


AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13). Data as JSON: /api/errors/e41697d505e24e2a. Report an issue: GitHub.