dotnet/wpf · error · ArgumentNullException

ArgumentNullException (buffer/sourceBuffer was IntPtr.Zero)

Error message

ArgumentNullException (buffer/sourceBuffer was IntPtr.Zero)

What it means

The internal WritePixelsImpl receives the pixel buffer as either an Array or an IntPtr. Historically, IntPtr.Zero caused a null-reference crash deep in native code; the library now deliberately throws ArgumentNullException named 'buffer' (backwards-compat path) or 'sourceBuffer' when the pointer is IntPtr.Zero.

Solutions

  1. Check the IntPtr for Zero before calling and throw or return early.
  2. Verify native allocation success (non-NULL) before passing pointers.
  3. For the Array overloads, pass a non-null array.

Example fix

// before
IntPtr p = AllocBufferMaybe();
bitmap.WritePixels(rect, p, stride, 0); // throws if p == IntPtr.Zero
// after
IntPtr p = AllocBufferMaybe();
if (p == IntPtr.Zero) throw new OutOfMemoryException("buffer alloc failed");
bitmap.WritePixels(rect, p, stride, 0);
Defensive patterns

Strategy: type-guard

Validate before calling

if (buffer == IntPtr.Zero) throw new ArgumentException("buffer must not be IntPtr.Zero");

Type guard

bool IsValidNativeBuffer(IntPtr p) => p != IntPtr.Zero;

Try / catch

try { bitmap.WritePixels(rect, ptr, stride, 0); } catch (ArgumentNullException) { /* fix allocation */ }

Prevention

When it happens

Trigger: Calling the IntPtr overload WritePixels(sourceRect, IntPtr buffer, ...) with IntPtr.Zero, or passing a pointer from an uninitialized/unallocated native buffer in backwardsCompat mode.

Common situations: Interop with native code where allocation failed silently and returned NULL; default-constructed IntPtr passed along; Marshal.AllocHGlobal result not checked.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/6ff919ea0b4fe939. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationCore/System/Windows/Media/Imaging/WriteableBitmap.cs:833

            {
                HRESULT.Check(MS.Win32.NativeMethods.E_INVALIDARG);
            }
            else if (destinationX < 0 || destinationY < 0)
            {
                HRESULT.Check((int)WinCodecErrors.WINCODEC_ERR_VALUEOVERFLOW);
            }

            //
            // Sanitize the other parameters.
            //
            if (sourceBuffer == IntPtr.Zero)
            {
                // Backwards Compat:
                //
                // The original code would null-ref when it was passed a null
                // buffer (IntPtr.Zero).  We choose to throw a better
                // exception.
                throw new ArgumentNullException(backwardsCompat ? "buffer" : "sourceBuffer");
            }

            Debug.Assert(!(backwardsCompat && sourceBufferStride < 1));
            ArgumentOutOfRangeException.ThrowIfNegativeOrZero(sourceBufferStride);

            if (sourceRect.Width == 0 || sourceRect.Height == 0)
            {
                Debug.Assert(!backwardsCompat);

                // Nothing to do.
                return;
            }

            checked
            {
                uint finalRowWidthInBits = (uint)((sourceRect.X + sourceRect.Width) * _format.InternalBitsPerPixel);
                uint finalRowWidthInBytes = ((finalRowWidthInBits + 7) / 8);
                uint requiredBufferSize = ((uint)(sourceRect.Y + sourceRect.Height - 1) * (uint)sourceBufferStride) + finalRowWidthInBytes;

View on GitHub (pinned to 81131a70a4)