stride3d/stride · error · InvalidOperationException

is a null

Error message

{ nameof(Heightmap) } is a null

What it means

HeightStickArraySourceFromHeightmap.CopyTo copies heightmap data into a heightstick array. It first requires the Heightmap reference to be non-null; otherwise it throws InvalidOperationException, since no height data exists to copy.

Solutions

  1. Assign a valid heightmap to the source before calling CopyTo.
  2. Check IsValid() (which returns false when Heightmap is null or invalid) before copying.
  3. Fix the missing/broken heightmap asset reference in the collider/scene asset.
  4. Load the heightmap asset before building the heightfield collider.

Example fix

// before
heightmapSource.CopyTo(heightStickArray, 0); // throws if Heightmap null
// after
if (heightmapSource.IsValid())
    heightmapSource.CopyTo(heightStickArray, 0);
Defensive patterns

Strategy: validation

Validate before calling

if (!heightmapSource.IsValid())
    return; // Heightmap null or invalid

Try / catch

try { heightmapSource.CopyTo(heightStickArray, 0); }
catch (InvalidOperationException ex) { /* heightmap not assigned; fix asset reference */ }

Prevention

When it happens

Trigger: Calling CopyTo when the Heightmap property was never assigned (or was set to null), e.g. a heightfield collider component referencing a heightmap asset that is null/not loaded.

Common situations: A HeightfieldColliderShape asset whose heightmap field is empty; heightmap asset failed to load or was removed from the content project; deserializing a scene with a missing heightmap reference.

Related errors


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

Appendix: source

Thrown at sources/engine/Stride.Physics/HeightStickArraySourceFromHeightmap.cs:36

        public Heightmap Heightmap { get; set; }

        [DataMemberIgnore]
        public HeightfieldTypes HeightType => Heightmap?.HeightType ?? default;

        [DataMemberIgnore]
        public Int2 HeightStickSize => Heightmap?.Size ?? default;

        [DataMemberIgnore]
        public Vector2 HeightRange => Heightmap?.HeightRange ?? default;

        [DataMemberIgnore]
        public float HeightScale => Heightmap?.HeightScale ?? default;

        public bool IsValid() => Heightmap?.IsValid() ?? false;

        public void CopyTo<T>(UnmanagedArray<T> heightStickArray, int index) where T : struct
        {
            if (Heightmap == null) throw new InvalidOperationException($"{ nameof(Heightmap) } is a null");
            if (heightStickArray == null) throw new ArgumentNullException(nameof(heightStickArray));

            var heightStickArrayLength = heightStickArray.Length - index;
            if (heightStickArrayLength <= 0) throw new IndexOutOfRangeException(nameof(index));

            var typeOfT = typeof(T);
            T[] heights;

            if (typeOfT == typeof(float))
            {
                if (Heightmap.Floats == null) throw new InvalidOperationException($"{ nameof(Heightmap.Floats) } is a null.");
                heights = (T[])(object)Heightmap.Floats;
            }
            else if (typeOfT == typeof(short))
            {
                if (Heightmap.Shorts == null) throw new InvalidOperationException($"{ nameof(Heightmap.Shorts) } is a null.");
                heights = (T[])(object)Heightmap.Shorts;
            }

View on GitHub (pinned to 96fad776d2)