stride3d/stride · error · InvalidOperationException
Invalid stride [ ]. Value can't be lower than actual stride…
Error message
Invalid stride [{rowStride}]. Value can't be lower than actual stride [{rowPitch}] What it means
When setting up a per-pixel-buffer view (PixelBuffer) with a user-supplied rowStride, the stride must be at least the naturally computed row pitch for the format and width. A smaller stride would make rows overlap/corrupt data, so Initialize/TextureData setup throws. The rowPitch is computed by ComputePitch from the pixel format and width.
Solutions
- Pass rowStride >= rowPitch (rowPitch = width * bytes-per-pixel for unpacked formats).
- Pass rowStride = 0 to let Stride compute the tight pitch automatically.
- Recompute the stride with the same formula Stride uses (Image.ComputePitch) for the format and width.
- Check whether you accidentally passed the stride of mip level 1+ instead of level 0.
Example fix
// before var buf = new PixelBuffer(w, h, format, ptr, rowStride: w); // pixels, not bytes // after int bpp = format.SizeInBytes(); var buf = new PixelBuffer(w, h, format, ptr, rowStride: w * bpp);
Defensive patterns
Strategy: validation
Validate before calling
Image.ComputePitch(format, w, h, out var rowPitch, out _, out _, out _, PitchFlags.None);
if (rowStride > 0 && rowStride < rowPitch)
throw new ArgumentException($"rowStride {rowStride} < required {rowPitch} bytes/row."); Type guard
null
Try / catch
try { buf = new PixelBuffer(w, h, format, ptr, 0, rowStride); }
catch (InvalidOperationException ex) when (ex.Message.StartsWith("Invalid stride"))
{
rowStride = 0; // let Stride compute tight pitch
buf = new PixelBuffer(w, h, format, ptr, 0, rowStride);
} Prevention
- Remember stride is in bytes, not pixels.
- Use rowStride = 0 unless you know the buffer's real row padding.
- Never reuse a smaller mip's stride for level 0.
- Compute expected pitch once with Image.ComputePitch and assert against it.
When it happens
Trigger: Passing a rowStride smaller than ComputePitch's rowPitch for the given format/width — e.g. stride 512 for a 256-wide R8G8B8A8_UNorm image (which needs 1024 bytes per row).
Common situations: Confusing row stride in bytes with pixel count; wrapping a tightly packed buffer with a stride copied from a smaller mip level; unit mistakes (stride in pixels vs bytes).
Understand the failure class
Background: "value must be between 0 and 1" / "out of range" / "must not be negative" errors: fixing range-validation failures across open-source libraries — this error's family across 42 libraries.
Related errors
- Cannot specify custom stride with mipmaps
- Custom strides is not supported with packed PixelFormats
- Invalid Width/Height/Depth/ArraySize for Image 1D
- Invalid Width/Height/Depth/ArraySize for Image 2D
- Invalid Width/Height/Depth/ArraySize for Image 3D
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/3a80d9cf0c86c391.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Foundation/Graphics/Image.cs:1027
bufferCount = 0;
var mipmapToZIndex = new List<int>();
for (int j = 0; j < imageDesc.ArraySize; j++)
{
int w = imageDesc.Width;
int h = imageDesc.Height;
int d = imageDesc.Depth;
for (int i = 0; i < imageDesc.MipLevels; i++)
{
ComputePitch(imageDesc.Format, w, h, out var rowPitch, out var slicePitch, out var widthPacked, out var heightPacked, pitchFlags);
if (rowStride > 0)
{
// Check that stride is ok
if (rowStride < rowPitch)
throw new InvalidOperationException($"Invalid stride [{rowStride}]. Value can't be lower than actual stride [{rowPitch}]");
if (widthPacked != w || heightPacked != h)
throw new InvalidOperationException("Custom strides is not supported with packed PixelFormats");
// Recalculate slice pitch
slicePitch = rowStride * h;
}
// Store the number of z-slicec per miplevels
if (j == 0)
mipmapToZIndex.Add(bufferCount);
// Keep a trace of indices for the 1st array size, for each mip levels
pixelSizeInBytes += d * slicePitch;
bufferCount += d;
if (h > 1)
h >>= 1;View on GitHub (pinned to 96fad776d2)