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
- Check stream.CanRead before calling LoadFromStream and surface a clear error if false.
- Open the source file with FileAccess.Read (not Write or ReadWrite-with-closed-handle).
- For MemoryStream, ensure it was constructed from a readable source and not disposed.
- 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
- Open font files with FileAccess.Read.
- Do not reuse disposed or write-only streams for font loading.
- Check CanRead and reset Position before LoadFromStream.
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
- The parameter value must be greater than zero.
- Can not create '{name}' because a directory with the same na
- Can not create '{name}' because a file with the same name al
- Failed to open content stream
- Default font family name can't be null or empty.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/e41697d505e24e2a.
Report an issue: GitHub.