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

  1. Set description.MipLevels = 1 when a custom rowStride is required.
  2. Generate mipmaps yourself afterwards (e.g. via ToMemoryImage/mipmap generation per level) instead of passing a mip chain with one stride.
  3. Drop the custom rowStride and let Stride's ComputePitch compute tightly packed strides if the buffer is tightly packed.
  4. 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

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


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)