stride3d/stride · error · ArgumentException
Pointer cannot be equal to IntPtr.Zero
Error message
Pointer cannot be equal to IntPtr.Zero
What it means
The PixelBuffer constructor requires a non-null native pointer because the buffer is a view over existing pixel memory, never an owner. Passing IntPtr.Zero would produce a buffer whose DataPointer is invalid, so the constructor throws ArgumentException for the dataPointer argument.
Solutions
- Check the pointer for IntPtr.Zero before constructing and handle the failed allocation.
- Allocate memory with Marshal.AllocHGlobal or obtain a valid pointer from a staging resource before wrapping it.
- Use an Image/PixelBuffer factory that allocates internally instead of wrapping raw memory.
Example fix
// before
var pb = new PixelBuffer(w, h, format, rowStride, bufferStride, ptr);
// after
if (ptr == IntPtr.Zero) throw new OutOfMemoryException("pixel allocation failed");
var pb = new PixelBuffer(w, h, format, rowStride, bufferStride, ptr); Defensive patterns
Strategy: validation
Validate before calling
if (dataPointer == IntPtr.Zero)
throw new InvalidOperationException("Cannot wrap pixel data: native allocation returned zero"); Type guard
bool HasValidPointer(IntPtr p) => p != IntPtr.Zero;
Try / catch
try { var pb = new PixelBuffer(w, h, fmt, rowStride, bufferStride, ptr); }
catch (ArgumentException ex) when (ex.ParamName == "dataPointer") { log.Error("null pixel data pointer"); throw; } Prevention
- Always check the result of native allocations for IntPtr.Zero before wrapping.
- Wrap pointer creation and PixelBuffer construction in the same helper.
- Prefer factory methods (Image.New) that own allocation over raw-pointer constructors.
When it happens
Trigger: Calling new PixelBuffer(width, height, format, rowStride, bufferStride, dataPointer) with dataPointer == IntPtr.Zero, typically when a native allocation (e.g. from a GPU staging readback or Marshal.AllocHGlobal) returned zero or was not yet initialized.
Common situations: Interop code where a native allocation failed and returned IntPtr.Zero; calling the constructor before a staging texture readback populated the pointer; mis-ordered init code where the pointer field is still default(IntPtr).
Related errors
- Invalid destination pixelBufferArray. Must have the same…
- Invalid sizeof(T), not a multiple of current size
- Could not find a load operation right before Interop.Pin
- Could not find a store operation right after Interop.Pin
- The camera [ ] is disabled and can't be attached
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/e88c1c837fe9aa7f.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Foundation/Graphics/PixelBuffer.cs:66
/// <summary>
/// True when RowStride == sizeof(pixelformat) * width
/// </summary>
private readonly bool isStrictRowStride;
/// <summary>
/// Initializes a new instance of the <see cref="PixelBuffer" /> struct.
/// </summary>
/// <param name="width">The width.</param>
/// <param name="height">The height.</param>
/// <param name="format">The format.</param>
/// <param name="rowStride">The row pitch.</param>
/// <param name="bufferStride">The slice pitch.</param>
/// <param name="dataPointer">The pixels.</param>
public PixelBuffer(int width, int height, PixelFormat format, int rowStride, int bufferStride, IntPtr dataPointer)
{
if (dataPointer == IntPtr.Zero)
throw new ArgumentException("Pointer cannot be equal to IntPtr.Zero", "dataPointer");
this.width = width;
this.height = height;
this.format = format;
this.rowStride = rowStride;
this.bufferStride = bufferStride;
this.dataPointer = dataPointer;
this.pixelSize = format.SizeInBytes;
this.isStrictRowStride = (pixelSize * width) == rowStride;
}
/// <summary>
/// Gets the width.
/// </summary>
/// <value>The width.</value>
public int Width { get { return width; } }
/// <summary>View on GitHub (pinned to 96fad776d2)