AvaloniaUI/Avalonia · error · ArgumentOutOfRangeException
sourceRect
Error message
sourceRect
What it means
Bitmap.ValidateSourceRect's first guard rejects a sourceRect that has non-positive Width or Height AND a non-zero X or Y. The intent: zero width/height is treated as 'default to full bitmap' only when X=Y=0; a rect with both a non-zero offset and a zero extent is meaningless.
Source
Thrown at src/Avalonia.Base/Media/Imaging/Bitmap.cs:205
public void Save(Stream stream, int? quality = null)
{
PlatformImpl.Item.Save(stream, PngBitmapEncoderOptions.Default);
}
/// <inheritdoc />
public void Save(Stream stream, BitmapEncoderOptions options)
{
PlatformImpl.Item.Save(stream, options);
}
public virtual PixelFormat? Format => (PlatformImpl.Item as IReadableBitmapImpl)?.Format;
public virtual AlphaFormat? AlphaFormat => (PlatformImpl.Item as IReadableBitmapImpl)?.AlphaFormat;
private PixelRect ValidateSourceRect(PixelRect sourceRect)
{
if ((sourceRect.Width <= 0 || sourceRect.Height <= 0) && (sourceRect.X != 0 || sourceRect.Y != 0))
throw new ArgumentOutOfRangeException(nameof(sourceRect));
if (sourceRect.X < 0 || sourceRect.Y < 0)
throw new ArgumentOutOfRangeException(nameof(sourceRect));
if (sourceRect.Width <= 0)
sourceRect = sourceRect.WithWidth(PixelSize.Width);
if (sourceRect.Height <= 0)
sourceRect = sourceRect.WithHeight(PixelSize.Height);
if (sourceRect.Right > PixelSize.Width || sourceRect.Bottom > PixelSize.Height)
throw new ArgumentOutOfRangeException(nameof(sourceRect));
return sourceRect;
}
/// <summary>
/// Performs a row-by-row copy of pixels from a source buffer into a destination buffer.
/// </summary>
/// <remarks>View on GitHub (pinned to 11c5427268)
Solutions
- If the intent is 'no sub-rect', pass PixelRect.Empty or new PixelRect(0,0,0,0) so the defaulting branch applies.
- Guard before the call: if (rect.Width <= 0 || rect.Height <= 0) rect = new PixelRect(rect.X, rect.Y, bmp.PixelSize.Width - rect.X, bmp.PixelSize.Height - rect.Y);
- Clamp selection rectangles so X=0 when width is zero, or never let width/height reach zero with a non-zero origin.
- Add an assertion in your crop logic to surface zero-extent off-origin rectangles early.
Example fix
// before
bmp.CopyPixels(new PixelRect(10, 10, 0, 0), ...); // throws
// after
var r = new PixelRect(10, 10, 0, 0);
if (r.Width <= 0 || r.Height <= 0)
r = new PixelRect(0, 0, 0, 0); // signal 'use whole bitmap'
bmp.CopyPixels(r, ...); Defensive patterns
Strategy: validation
Validate before calling
static PixelRect NormalizeSourceRect(PixelRect r, PixelSize bmp)
{
if (r.Width <= 0 || r.Height <= 0)
{
if (r.X != 0 || r.Y != 0)
r = new PixelRect(0, 0, 0, 0); // signal 'whole bitmap'
}
return r;
} Prevention
- Pass PixelRect.Empty (0,0,0,0) to mean 'whole bitmap'.
- Never let a selection rect have a non-zero origin with a zero extent.
- Add a debug assertion for off-origin zero-extent rectangles.
When it happens
Trigger: Calling CopyPixels/Save with a sourceRect = new PixelRect(x, y, 0, h) or (x, y, w, 0) where x or y != 0; passing a source rectangle computed from a selection whose width/height collapsed but whose origin moved.
Common situations: A cropping UI where the user dragged the selection to zero width but kept it off the origin; binding sourceRect fields from sliders that can individually zero out; computing a sub-rect from a layout that yields a zero dimension with an offset.
Related errors
- stride
- bufferSize
- The parameter value cannot be greater than '{MaxFontEmSize}'
- Stream is not readable
- The parameter value must be greater than zero.
AI-assisted analysis of AvaloniaUI/Avalonia@11c5427268 (2026-08-13).
Data as JSON: /api/errors/694b7d6d237cabea.
Report an issue: GitHub.