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

  1. If the intent is 'no sub-rect', pass PixelRect.Empty or new PixelRect(0,0,0,0) so the defaulting branch applies.
  2. 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);
  3. Clamp selection rectangles so X=0 when width is zero, or never let width/height reach zero with a non-zero origin.
  4. 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

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


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