stride3d/stride · error · InvalidOperationException
Cannot specify custom stride with mipmaps
Error message
Cannot specify custom stride with mipmaps
What it means
Image.Initialize only allows a custom row stride (rowStride > 0) when the image has exactly one mip level. With mipmaps, each mip level has a different pitch, so a single user-supplied stride cannot describe them all; the API rejects the combination up front rather than producing corrupted mip data.
Solutions
- Set description.MipLevels = 1 when a custom rowStride is required.
- Generate mipmaps yourself afterwards (e.g. via ToMemoryImage/mipmap generation per level) instead of passing a mip chain with one stride.
- Drop the custom rowStride and let Stride's ComputePitch compute tightly packed strides if the buffer is tightly packed.
- Re-pack the external buffer so each mip starts contiguously and load it without a custom stride.
Example fix
// before var img = Image.New(desc, dataPointer, 0, null, false, PitchFlags.None, rowStride: 256, mipLevels: 4); // after desc.MipLevels = 1; // custom stride only valid for single-mip images var img = Image.New(desc, dataPointer, 0, null, false, PitchFlags.None, rowStride: 256);
Defensive patterns
Strategy: validation
Validate before calling
if (rowStride > 0 && desc.MipLevels != 1)
throw new ArgumentException("Custom rowStride requires MipLevels == 1; generate mips separately."); Type guard
null
Try / catch
try { img = Image.New(desc, ptr, 0, null, false, flags, rowStride); }
catch (InvalidOperationException ex) when (ex.Message.Contains("custom stride with mipmaps"))
{
desc.MipLevels = 1;
img = Image.New(desc, ptr, 0, null, false, flags, rowStride);
} Prevention
- Only pass rowStride when MipLevels is exactly 1.
- Generate mipmaps after importing the single-mip image.
- Prefer rowStride = 0 (tight packing) unless wrapping external padded buffers.
- Document stride semantics (bytes per row) in your texture-loading helper.
When it happens
Trigger: Calling Image.New with rowStride set (or a PitchFlags-based layout with a custom stride) while description.MipLevels is anything other than 1 (or trueMipmapChain / MipLevels > 1).
Common situations: Wrapping externally allocated memory (e.g. a decoder output buffer with padded rows) into a Stride Image while keeping the source texture's mip count; porting code from APIs (DirectXTex) where per-mip strides are allowed.
Understand the failure class
Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.
Related errors
- Unsupported DXGI Format
- Invalid Width/Height/Depth/ArraySize for Image 1D
- Invalid Width/Height/Depth/ArraySize for Image 2D
- TextureCube must have an arraysize = 6
- Invalid Width/Height/Depth/ArraySize for Image 3D
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/86bed5ecab21740f.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Foundation/Graphics/Image.cs:769
static Image()
{
Register(ImageFileType.Stride, ImageHelper.LoadFromMemory, ImageHelper.SaveFromMemory);
Register(ImageFileType.Dds, DDSHelper.LoadFromDDSMemory, DDSHelper.SaveToDDSStream);
Register(ImageFileType.Gif, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveGifFromMemory);
Register(ImageFileType.Tiff, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveTiffFromMemory);
Register(ImageFileType.Bmp, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveBmpFromMemory);
Register(ImageFileType.Jpg, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveJpgFromMemory);
Register(ImageFileType.Png, StandardImageHelper.LoadFromMemory, StandardImageHelper.SavePngFromMemory);
}
internal unsafe void Initialize(ImageDescription description, IntPtr dataPointer, int offset, GCHandle? handle, bool bufferIsDisposable, PitchFlags pitchFlags = PitchFlags.None, int rowStride = 0)
{
if (!description.Format.IsValid || description.Format.IsVideoFormat)
throw new InvalidOperationException("Unsupported DXGI Format");
if (rowStride > 0 && description.MipLevels != 1)
throw new InvalidOperationException("Cannot specify custom stride with mipmaps");
this.handle = handle;
switch (description.Dimension)
{
case TextureDimension.Texture1D:
if (description.Width <= 0 || description.Height != 1 || description.Depth != 1 || description.ArraySize == 0)
throw new InvalidOperationException("Invalid Width/Height/Depth/ArraySize for Image 1D");
// Check that miplevels are fine
description.MipLevels = CalculateMipLevels(description.Width, 1, description.MipLevels);
break;
case TextureDimension.Texture2D:
case TextureDimension.TextureCube:
if (description.Width <= 0 || description.Height <= 0 || description.Depth != 1 || description.ArraySize == 0)
throw new InvalidOperationException("Invalid Width/Height/Depth/ArraySize for Image 2D");
View on GitHub (pinned to 96fad776d2)