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

  1. Pass rowStride >= rowPitch (rowPitch = width * bytes-per-pixel for unpacked formats).
  2. Pass rowStride = 0 to let Stride compute the tight pitch automatically.
  3. Recompute the stride with the same formula Stride uses (Image.ComputePitch) for the format and width.
  4. 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

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


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)