[Bug] [UE 5.8.1] Procedural Vegetation: Grower node crashes editor — "Assertion failed: Point" (PVGrower.cpp:1004), light detection resolves only 2 points

Summary

The Grower node in the Procedural Vegetation Editor reliably hard-crashes the editor with Assertion failed: Point at PVGrower.cpp:1004, on Apple Silicon / Metal. It reproduced 3/3 in earlier testing on this machine, including on a brand-new Procedural Vegetation asset with default settings, and was re-verified today on the stock engine plugin (the callstack below is from today’s run).

There is no workaround: DetectLight() is the first call in ExecuteGrowthCycle() and is completely unconditional, so it is NOT avoided by leaving the Phototropism or LightSenescence pins disconnected. The only console variable the plugin registers (PV.DebugMode.Enabled, PVUtilities.cpp) has no effect on it.

At PVGrower.cpp:1004 the code reads:

UPVGrowerPoint* Point = Skeleton->GetPoint(Data.PointNumber);
check(Point);
if (Point)      // <-- the null case is ALREADY handled here
{ ... }

Data.PointNumber originates from the GPU readback in FPVLightDetection::ExecuteLightDetection. Those point numbers do not resolve against the skeleton, so GetPoint() returns null — and the check() sitting directly above an existing null guard escalates an already-handled condition into a fatal editor crash. One more site in the same function has this assert-then-guard shape (the branch-light loop, where the next line is if (Point && Point->Bud.Status.Triggered == 0)); several further check(Point)/check(Primitive) sites in this file dereference the pointer with no guard at all, so they would crash on the same bad data even with the assertions compiled out.

Environment: UE 5.8.1, ++UE5+Release-5.8-CL-56057345 (Launcher binary, Development). macOS 26.3 (Darwin 25.3.0), MacBook Pro 18,1 / Apple M1 Pro / 16 GB. RHI: Metal, SM6.

What Type of Bug are you experiencing?

World Creation Tools

Steps to Reproduce

  1. Create a new project from the Third Person template.
  2. Enable the Procedural Vegetation Editor plugin and restart the editor.
  3. Create a new Procedural Vegetation asset in the Content Browser.
  4. Add a Grower node to the graph with default settings — no parameter changes, and nothing connected to the Phototropism or LightSenescence pins.
  5. Evaluate / execute the graph.

Expected Result

The Grower node evaluates and produces a plant skeleton, with light detection resolving the skeleton’s points.

Observed Result

The editor hard-crashes immediately with a fatal assertion (not a soft error or graph warning), terminating the session and losing unsaved work. Reproduced 3/3 in earlier testing (including a brand-new asset with stock defaults), and re-verified today on the stock 5.8.1 engine plugin — the attached callstack is from today’s crash.

Affects Versions

5.8

Platform(s)

Mac

For crash reports, include your callstack

Assertion failed: Point [File:./../Plugins/Experimental/ProceduralVegetationEditor/Source/ProceduralVegetation/Private/Implementations/PVGrower.cpp] [Line: 1004]

SIGSEGV: invalid attempt to access memory at address 0x3

0x066de274 libUnrealEditor-Core.dylib!FGenericPlatformMisc::RaiseException(unsigned int)
0x068a23ec libUnrealEditor-Core.dylib!FMacErrorOutputDevice::Serialize(char16_t const*, ELogVerbosity::Type, FName const&)
0x06a1c328 libUnrealEditor-Core.dylib!FOutputDevice::LogfImpl(char16_t const*, …)
0x06917b30 libUnrealEditor-Core.dylib!FDebug::CheckVerifyFailedImpl2V(char const*, char const*, int, char16_t const*, char*)
0x0691219c libUnrealEditor-Core.dylib!FDebug::CheckVerifyFailedImpl2(char const*, char const*, int, char16_t const*, …)
0x50e879ac libUnrealEditor-ProceduralVegetation.dylib!FPVGrower::ProcessPointLightData(UPVGrowerData*, TArray<FPVPointLightVectorData, TSizedDefaultAllocator<32>> const&) (.cold.1)
0x50d7c85c libUnrealEditor-ProceduralVegetation.dylib!FPVGrower::ProcessPointLightData(UPVGrowerData*, TArray<FPVPointLightVectorData, TSizedDefaultAllocator<32>> const&)
0x50d77af0 libUnrealEditor-ProceduralVegetation.dylib!FPVGrower::DetectLight(UPVGrowerData*, FPVColliderMeshData const&, FPVLeafMeshGeometry const&, TArray<FPVLeafTransform, TSizedDefaultAllocator<32>> const&, int)
0x50d77560 libUnrealEditor-ProceduralVegetation.dylib!FPVGrower::ExecuteGrowthCycle(FPVGrowerParams const&, UPVGrowerData*, int, FPVColliderMeshData const&)
0x50d6e154 libUnrealEditor-ProceduralVegetation.dylib!FPVGrower::IterateGrowthCycles(FPVGrowerParams const&, UPVGrowerData*)
0x50d6dbe8 libUnrealEditor-ProceduralVegetation.dylib!FPVGrower::Grow(FPVSeedPoint const&, FPVGrowerParams const&, FManagedArrayCollection&, bool)
0x50e1e6b4 libUnrealEditor-ProceduralVegetation.dylib!FPVGrowerElement::ExecuteInternal(FPCGContext*) const
0x58f2ac00 libUnrealEditor-PCG.dylib!IPCGElement::Execute(FPCGContext*) const
0x58ce8140 libUnrealEditor-PCG.dylib!FPCGGraphExecutor::Execute(double&)
0x5903039c libUnrealEditor-PCG.dylib!non-virtual thunk to UPCGEngineSubsystem::Tick(float)
0x17a2f0bc libUnrealEditor-Engine.dylib!FTickableGameObject::TickObjects(UWorld*, ELevelTick, bool, float)
0x11330328 libUnrealEditor-UnrealEd.dylib!UEditorEngine::Tick(float, bool)
0x11e8dc90 libUnrealEditor-UnrealEd.dylib!UUnrealEdEngine::Tick(float, bool)
0x027251d8 UnrealEditor!FEngineLoop::Tick()
0x02729488 UnrealEditor!GuardedMain(char16_t const*)
0x02740afc UnrealEditor!-[UEAppDelegate runGameThread:]
0x068a1ac0 libUnrealEditor-Core.dylib!-[FCocoaGameThread main]
0xa16b37a0 Foundation!NSThread__start()
0x9fdfbc08 libsystem_pthread.dylib!_pthread_start()
0x9fdf6ba8 libsystem_pthread.dylib!thread_start()

Additional Notes

THE UNDERLYING DEFECT IS WORSE THAN THE CRASH

Replacing those check() calls with null guards in a local build lets the Grower run to completion, which makes the real problem measurable. Counting the point numbers returned by light detection that fail to resolve against the skeleton, across consecutive growth cycles of a single default plant (one instrumented run):

cycle | returned | unresolved | resolved
1 | 2 | 1 | 1
2 | 3 | 2 | 1
3 | 4 | 2 | 2
4 | 5 | 3 | 2
5 | 6 | 4 | 2
6 | 7 | 5 | 2
7 | 9 | 7 | 2

The number of successfully resolved points stays pinned at 2 while the total grows every cycle — 78% unresolved by cycle 7. Within the run this is consistent and monotonically worsening rather than intermittent, which suggests an index/mapping problem (the skeleton point lookup not accounting for points added during growth, or the readback indices being in a different index space than UPVGrowerData::GetPoint() expects) rather than random GPU readback corruption.

Note: these numbers are measured from an instrumented local build, since stock 5.8.1 crashes before it can produce them.

Consequence: even with the assertion removed, phototropism, light senescence and branch-light averaging run on almost no valid input — so simply removing the check() is not a complete fix.

NOT THE SAME AS UE-386321

Per its forum thread (the tracker entry itself is not publicly visible), UE-386321 covers an index-out-of-bounds in RawIndexBuffer.h during asset loading in packaged builds of Nanite PVE meshes, and does not reproduce in the editor. This report is an in-editor crash during growth simulation in the light-detection path, still present in 5.8.1.

Full editor log available on request.