stride3d/stride · error · ArgumentException
Can't handle included both of positive and negative in type.
Error message
Can't handle { nameof(heightRange) } included both of positive and negative in { heightType } type. What it means
Byte heightfields can only encode heights on one side of zero, because byte values are mapped into a range that cannot straddle both positive and negative with this conversion. CheckHeightParameters throws when a Byte-type heightmap's range has X negative and Y positive (signs summing to 0).
Solutions
- Shift the height range so it lies entirely on one side of zero (e.g. 0..max) for Byte type.
- Switch HeightType to Short or Float, which support ranges crossing zero.
- Offset the height data so the minimum becomes 0 and store the offset elsewhere.
- Validate with IsValid() and normalize the range before creating colliders.
Example fix
// before heightmap.HeightType = HeightfieldTypes.Byte; heightmap.HeightRange = new FloatRange(-10f, 10f); // after heightmap.HeightType = HeightfieldTypes.Byte; heightmap.HeightRange = new FloatRange(0f, 20f); // shift data by +10
Defensive patterns
Strategy: validation
Validate before calling
if (heightType == HeightfieldTypes.Byte && Math.Sign(range.X) + Math.Sign(range.Y) == 0) range = new FloatRange(0f, range.Y - range.X);
Type guard
bool ByteSafeRange(HeightfieldTypes t, FloatRange r) => t != HeightfieldTypes.Byte || (Math.Sign(r.X) + Math.Sign(r.Y)) != 0;
Try / catch
try { CheckHeightParameters(size, type, range, scale, true); } catch (ArgumentException) { /* shift range or switch to Short/Float */ } Prevention
- Use Byte type only for single-sign ranges
- Shift data so min becomes 0 for Byte
- Re-evaluate type when terrain crosses zero (elevation datum)
When it happens
Trigger: HeightType = HeightfieldTypes.Byte with a HeightRange like (-1, 1) or (-10, 100); using ConvertToByteHeights with a range crossing zero.
Common situations: Terrain with sea level at 0 where artists keep symmetric positive/negative ranges; switching HeightType from Short/Float to Byte without adjusting the range.
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
- should be 1 in type.
- parameters should be greater than or equal to 2.
- is 0.
- . should be greater than .
- is too short.
AI-assisted analysis of stride3d/stride@96fad776d2 (2026-09-14).
Data as JSON: /api/errors/c87818270000dfe5.
Report an issue: GitHub.
Appendix: source
Thrown at sources/engine/Stride.Physics/Engine/HeightmapUtils.cs:49
throw new ArgumentException($"{ nameof(heightScale) } should be 1 in { heightType } type.");
}
// HeightRange
if (heightRange.Y < heightRange.X)
{
throw new ArgumentException($"{ nameof(heightRange) }.{ nameof(heightRange.Y) } should be greater than { nameof(heightRange.X) }.");
}
if (Math.Abs((heightRange.Y / heightScale) - (heightRange.X / heightScale)) < 1)
{
throw new ArgumentException($"{ nameof(heightRange) } is too short.");
}
if ((heightType == HeightfieldTypes.Byte) &&
(Math.Sign(heightRange.X) + Math.Sign(heightRange.Y)) == 0)
{
throw new ArgumentException($"Can't handle { nameof(heightRange) } included both of positive and negative in { heightType } type.");
}
}
catch (ArgumentException)
{
if (throwExceptionWhenInvalid) throw;
return false;
}
return true;
}
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();View on GitHub (pinned to 96fad776d2)