stride3d/stride · error · ArgumentException

. and should be greater than 0.

Error message

{ nameof(newSize) }.{ nameof(newSize.X) } and { nameof(newSize.Y) } should be greater than 0.

What it means

HeightmapUtils.Resize<T> also requires the target newSize to have both dimensions >= 1; resizing to an empty or negative dimension is meaningless and throws ArgumentException immediately after the originalSize check.

Solutions

  1. Clamp newSize to at least (1,1) before calling Resize.
  2. Ensure the LOD/percentage logic cannot produce 0 (Math.Max(1, value)).
  3. Validate user/editor input for the target resolution.
  4. Call with literal known-good dimensions instead of computed ones when possible.

Example fix

// before
var resized = HeightmapUtils.Resize(pixels, originalSize, new Int2(0, lodScale));
// after
var newSize = new Int2(Math.Max(1, originalSize.X / lodScale), Math.Max(1, originalSize.Y / lodScale));
var resized = HeightmapUtils.Resize(pixels, originalSize, newSize);
Defensive patterns

Strategy: validation

Validate before calling

newSize = new Int2(Math.Max(1, newSize.X), Math.Max(1, newSize.Y));

Type guard

bool CanResize(Int2 from, Int2 to) => from.X >= 1 && from.Y >= 1 && to.X >= 1 && to.Y >= 1;

Try / catch

try { resized = HeightmapUtils.Resize(pixels, originalSize, newSize); } catch (ArgumentException) { /* clamp size and retry */ }

Prevention

When it happens

Trigger: Calling Resize with newSize = (0, 0) or (n, 0)/(0, n); computing the target size from a percentage (e.g. 0%) or from a null/empty source that produced 0.

Common situations: Configurable level-of-detail value set to 0; dynamic resolution computed from an unloaded source; UI inputs allowing 0 or negative sizes.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Physics/Engine/HeightmapUtils.cs:80

        public static float ConvertToFloatHeight(float minValue, float maxValue, float value) => MathUtil.InverseLerp(minValue, maxValue, MathUtil.Clamp(value, minValue, maxValue)) * 2 - 1;
        public static short ConvertToShortHeight(float minValue, float maxValue, float value) => (short)Math.Round(ConvertToFloatHeight(minValue, maxValue, value) * short.MaxValue, MidpointRounding.AwayFromZero);
        public static byte ConvertToByteHeight(float minValue, float maxValue, float value) => (byte)Math.Round(MathUtil.InverseLerp(minValue, maxValue, MathUtil.Clamp(value, minValue, maxValue)) * byte.MaxValue, MidpointRounding.AwayFromZero);

        public static float[] ConvertToFloatHeights(float[] values, float minValue, float maxValue) => values.Select((v) => ConvertToFloatHeight(minValue, maxValue, v)).ToArray();
        public static float[] ConvertToFloatHeights(short[] values, short minValue = short.MinValue, short maxValue = short.MaxValue) => values.Select((v) => ConvertToFloatHeight(minValue, maxValue, v)).ToArray();
        public static float[] ConvertToFloatHeights(byte[] values, byte minValue = byte.MinValue, byte maxValue = byte.MaxValue) => values.Select((v) => ConvertToFloatHeight(minValue, maxValue, v)).ToArray();

        public static short[] ConvertToShortHeights(float[] values, float minValue, float maxValue) => values.Select((v) => ConvertToShortHeight(minValue, maxValue, v)).ToArray();
        public static short[] ConvertToShortHeights(short[] values, short minValue = short.MinValue, short maxValue = short.MaxValue) => values.Select((v) => ConvertToShortHeight(minValue, maxValue, v)).ToArray();
        public static short[] ConvertToShortHeights(byte[] values, byte minValue = byte.MinValue, byte maxValue = byte.MaxValue) => values.Select((v) => ConvertToShortHeight(minValue, maxValue, v)).ToArray();

        public static byte[] ConvertToByteHeights(float[] values, float minValue, float maxValue) => values.Select((v) => ConvertToByteHeight(minValue, maxValue, v)).ToArray();
        public static byte[] ConvertToByteHeights(short[] values, short minValue = short.MinValue, short maxValue = short.MaxValue) => values.Select((v) => ConvertToByteHeight(minValue, maxValue, v)).ToArray();

        public static T[] Resize<T>(T[] pixels, Int2 originalSize, Int2 newSize)
        {
            if (originalSize.X < 1 || originalSize.Y < 1) throw new ArgumentException($"{ nameof(originalSize) }.{ nameof(originalSize.X) } and { nameof(originalSize.Y) } should be greater than 0.");
            if (newSize.X < 1 || newSize.Y < 1) throw new ArgumentException($"{ nameof(newSize) }.{ nameof(newSize.X) } and { nameof(newSize.Y) } should be greater than 0.");

            if (originalSize.Equals(newSize))
            {
                return pixels.ToArray();
            }

            var originalWidth = originalSize.X;
            var originalLength = originalSize.Y;
            var newWidth = newSize.X;
            var newLength = newSize.Y;

            var scaleX = (newWidth - 1) == 0 ? 0d : ((double)(originalWidth - 1)) / (newWidth - 1);
            var scaleY = (newLength - 1) == 0 ? 0d : ((double)(originalLength - 1)) / (newLength - 1);

            int GetOriginalIndex(int x, int y) =>
                (int)Math.Round(y * scaleY, MidpointRounding.AwayFromZero) * originalWidth +
                (int)Math.Round(x * scaleX, MidpointRounding.AwayFromZero);

View on GitHub (pinned to 96fad776d2)