AvaloniaUI/Avalonia · error · ArgumentOutOfRangeException
stride
Error message
stride
What it means
The WriteableBitmap(IntPtr data) constructor computes a minimum per-row stride = (format.BitsPerPixel * width + 7) / 8 and throws ArgumentOutOfRangeException(nameof(stride)) when the supplied stride is smaller than that minimum. The stride must accommodate at least one full row of source pixels so the per-row Unsafe.CopyBlock copies valid data.
Source
Thrown at src/Avalonia.Base/Media/Imaging/WriteableBitmap.cs:55
_pixelFormatMemory = pixelFormatMemory;
}
/// <summary>
/// Initializes a new instance of the <see cref="WriteableBitmap"/> class with existing pixel data
/// The data is copied to the bitmap
/// </summary>
/// <param name="format">The pixel format.</param>
/// <param name="alphaFormat">The alpha format.</param>
/// <param name="data">The pointer to the source bytes.</param>
/// <param name="size">The size of the bitmap in device pixels.</param>
/// <param name="dpi">The DPI of the bitmap.</param>
/// <param name="stride">The number of bytes per row.</param>
public unsafe WriteableBitmap(PixelFormat format, AlphaFormat alphaFormat, IntPtr data, PixelSize size, Vector dpi, int stride)
: this(size, dpi, format, alphaFormat)
{
var minStride = (format.BitsPerPixel * size.Width + 7) / 8;
if (minStride > stride)
throw new ArgumentOutOfRangeException(nameof(stride));
using (var locked = Lock())
{
for (var y = 0; y < size.Height; y++)
Unsafe.CopyBlock((locked.Address + locked.RowBytes * y).ToPointer(),
(data + y * stride).ToPointer(), (uint)minStride);
}
}
public override PixelFormat? Format => _pixelFormatMemory?.Format ?? base.Format;
public ILockedFramebuffer Lock()
{
if (_pixelFormatMemory == null)
return ((IWriteableBitmapImpl)PlatformImpl.Item).Lock();
return new LockedFramebuffer(_pixelFormatMemory.Address, _pixelFormatMemory.Size,
_pixelFormatMemory.RowBytes,View on GitHub (pinned to 11c5427268)
Solutions
- Compute stride from the format: stride = (format.BitsPerPixel * size.Width + 7) / 8, or larger.
- If the source buffer uses extra padding per row, pass the actual source row pitch and let Avalonia copy minStride bytes per row.
- Validate stride >= minStride before constructing.
Example fix
// before int stride = size.Width; // wrong for 32-bpp new WriteableBitmap(PixelFormat.Bgra8888, AlphaFormat.Premultiplied, data, size, dpi, stride); // after int stride = (PixelFormat.Bgra8888.BitsPerPixel * size.Width + 7) / 8; // 4*width new WriteableBitmap(PixelFormat.Bgra8888, AlphaFormat.Premultiplied, data, size, dpi, stride);
Defensive patterns
Strategy: validation
Validate before calling
int minStride = (format.BitsPerPixel * size.Width + 7) / 8;
if (stride < minStride)
throw new ArgumentOutOfRangeException(nameof(stride), $"stride must be >= {minStride}.");
var wb = new WriteableBitmap(format, alphaFormat, data, size, dpi, stride); Prevention
- Always compute stride from BitsPerPixel and width.
- Account for packed formats (sub-byte-per-pixel) with the (bits+7)/8 rounding.
- Pass the source buffer's real row pitch, not width.
When it happens
Trigger: Calling new WriteableBitmap(format, alphaFormat, data, size, dpi, stride) with a stride smaller than bitsPerPixel*width rounded up to bytes — e.g. passing width in bytes instead of the row pitch, or miscomputing bitsPerPixel for packed formats like BlackWhite/Gray2.
Common situations: Assuming stride = width (bytes) for a 32-bpp format; using width*sizeof(int) for a 16-bpp format; interop with a source buffer whose real pitch is larger but the caller passed the wrong value.
Related errors
- Size should be >= (1,1)
- stride
- bufferSize
- Pixel format {finalFormat} is not supported
- Transition elements have different parents.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/6c820b37f3628bcc.
Report an issue: GitHub.