stride3d/stride · error · InvalidOperationException

Width/Height/Depth must be power of 2

Error message

Width/Height/Depth must be power of 2

What it means

The 3D overload of Image.CalculateMipLevels requires Width/Height/Depth to be powers of two when mipLevels > 1, because mip generation for volume textures relies on clean halving. Non-power-of-two dimensions trigger an InvalidOperationException before any mip counting happens.

Solutions

  1. Resize width/height/depth to the next power of two before computing mip levels
  2. Use mipLevels <= 1 (no chain) if the size cannot be changed
  3. Preprocess the texture offline (e.g. in an asset pipeline step) to power-of-two dimensions

Example fix

// before
int mips = Image.CalculateMipLevels(100, 100, 100, 4);
// after
int size = 128; // next pow2
int mips = Image.CalculateMipLevels(size, size, size, 4);
Defensive patterns

Strategy: validation

Validate before calling

bool IsPow2(int v) => v > 0 && (v & (v - 1)) == 0;
if (mipLevels > 1 && !(IsPow2(w) && IsPow2(h) && IsPow2(d)))
    // resize to next power of two first

Type guard

bool CanGenerateVolumeMips(int w, int h, int d, int mips) => mips <= 1 || (IsPow2(w) && IsPow2(h) && IsPow2(d));

Try / catch

try { mips = Image.CalculateMipLevels(w, h, d, count); }
catch (InvalidOperationException) { w = NextPow2(w); h = NextPow2(h); d = NextPow2(d); mips = Image.CalculateMipLevels(w, h, d, count); }

Prevention

When it happens

Trigger: Calling CalculateMipLevels(width, height, depth, mipLevels) with mipLevels > 1 and any of width, height, depth not a power of two — e.g. 100x100x100 with 4 mips.

Common situations: Importing artwork with arbitrary dimensions (e.g. 1920x1080) and requesting a mip chain; volume textures from medical/scientific data with non-PoT sizes; forgetting to pad/resize before mip generation.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14). Data as JSON: /api/errors/f7f40ec311a2f4a3. Report an issue: GitHub.

Appendix: source

Thrown at sources/engine/Stride.Foundation/Graphics/Image.cs:674

                mipLevels = 1;
            }
            return mipLevels;
        }

        /// <summary>
        /// Calculates the number of miplevels for a Texture 2D.
        /// </summary>
        /// <param name="width">The width of the texture.</param>
        /// <param name="height">The height of the texture.</param>
        /// <param name="depth">The depth of the texture.</param>
        /// <param name="mipLevels">A <see cref="MipMapCount"/>, set to true to calculates all mipmaps, to false to calculate only 1 miplevel, or > 1 to calculate a specific amount of levels.</param>
        /// <returns>The number of miplevels.</returns>
        public static int CalculateMipLevels(int width, int height, int depth, MipMapCount mipLevels)
        {
            if (mipLevels > 1)
            {
                if (!IsPow2(width) || !IsPow2(height) || !IsPow2(depth))
                    throw new InvalidOperationException("Width/Height/Depth must be power of 2");

                int maxMips = CountMips(width, height, depth);
                if (mipLevels > maxMips)
                    throw new InvalidOperationException($"MipLevels must be <= {maxMips}");
            }
            else if (mipLevels == 0)
            {
                if (!IsPow2(width) || !IsPow2(height) || !IsPow2(depth))
                    throw new InvalidOperationException("Width/Height/Depth must be power of 2");

                mipLevels = CountMips(width, height, depth);
            }
            else
            {
                mipLevels = 1;
            }
            return mipLevels;
        }

View on GitHub (pinned to 96fad776d2)