{"record":{"id":"86bed5ecab21740f","repo":"stride3d/stride","slug":"cannot-specify-custom-stride-with-mipmaps","errorCode":null,"errorMessage":"Cannot specify custom stride with mipmaps","messagePattern":"Cannot specify custom stride with mipmaps","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"sources/engine/Stride.Foundation/Graphics/Image.cs","lineNumber":769,"sourceCode":"\n        static Image()\n        {\n            Register(ImageFileType.Stride, ImageHelper.LoadFromMemory, ImageHelper.SaveFromMemory);\n            Register(ImageFileType.Dds, DDSHelper.LoadFromDDSMemory, DDSHelper.SaveToDDSStream);\n            Register(ImageFileType.Gif, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveGifFromMemory);\n            Register(ImageFileType.Tiff, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveTiffFromMemory);\n            Register(ImageFileType.Bmp, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveBmpFromMemory);\n            Register(ImageFileType.Jpg, StandardImageHelper.LoadFromMemory, StandardImageHelper.SaveJpgFromMemory);\n            Register(ImageFileType.Png, StandardImageHelper.LoadFromMemory, StandardImageHelper.SavePngFromMemory);\n        }\n\n        internal unsafe void Initialize(ImageDescription description, IntPtr dataPointer, int offset, GCHandle? handle, bool bufferIsDisposable, PitchFlags pitchFlags = PitchFlags.None, int rowStride = 0)\n        {\n            if (!description.Format.IsValid || description.Format.IsVideoFormat)\n                throw new InvalidOperationException(\"Unsupported DXGI Format\");\n\n            if (rowStride > 0 && description.MipLevels != 1)\n                throw new InvalidOperationException(\"Cannot specify custom stride with mipmaps\");\n\n            this.handle = handle;\n\n            switch (description.Dimension)\n            {\n                case TextureDimension.Texture1D:\n                    if (description.Width <= 0 || description.Height != 1 || description.Depth != 1 || description.ArraySize == 0)\n                        throw new InvalidOperationException(\"Invalid Width/Height/Depth/ArraySize for Image 1D\");\n\n                    // Check that miplevels are fine\n                    description.MipLevels = CalculateMipLevels(description.Width, 1, description.MipLevels);\n                    break;\n\n                case TextureDimension.Texture2D:\n                case TextureDimension.TextureCube:\n                    if (description.Width <= 0 || description.Height <= 0 || description.Depth != 1 || description.ArraySize == 0)\n                        throw new InvalidOperationException(\"Invalid Width/Height/Depth/ArraySize for Image 2D\");\n","sourceCodeStart":751,"sourceCodeEnd":787,"githubUrl":"https://github.com/stride3d/stride/blob/96fad776d210c221682aac1ccdf4c79dc046fc38/sources/engine/Stride.Foundation/Graphics/Image.cs#L751-L787","documentation":"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.","triggerScenarios":"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).","commonSituations":"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.","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."],"exampleFix":"// before\nvar img = Image.New(desc, dataPointer, 0, null, false, PitchFlags.None, rowStride: 256, mipLevels: 4);\n// after\ndesc.MipLevels = 1; // custom stride only valid for single-mip images\nvar img = Image.New(desc, dataPointer, 0, null, false, PitchFlags.None, rowStride: 256);","handlingStrategy":"validation","validationCode":"if (rowStride > 0 && desc.MipLevels != 1)\n    throw new ArgumentException(\"Custom rowStride requires MipLevels == 1; generate mips separately.\");","typeGuard":"null","tryCatchPattern":"try { img = Image.New(desc, ptr, 0, null, false, flags, rowStride); }\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"custom stride with mipmaps\"))\n{\n    desc.MipLevels = 1;\n    img = Image.New(desc, ptr, 0, null, false, flags, rowStride);\n}","preventionTips":["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."],"tags":["graphics","textures","mipmaps","stride"],"backgroundTag":"conflicting-config-options","analyzedSha":"96fad776d210c221682aac1ccdf4c79dc046fc38","analyzedAt":"2026-09-14T02:59:31.279Z","contentChangedAt":"2026-09-14T02:59:31.279Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}