Crash: check(Event.IsValid()) in StateTreeEvents.h:119 — CaptureNewStateEvents treats an unchanged frame's states as newly entered

Summary

FStateTreeExecutionContext::CaptureNewStateEvents (StateTreeExecutionContext.cpp, ~line 2503) initializes UniqueStates to all of NewFrame.ActiveStates and only narrows it when the StateID comparison loop finds a divergence. For a frame whose active states are fully identical to the previous frame (an untouched parent frame while a transition re-selects inside a linked-asset frame below it), the loop never breaks, so every state is treated as newly entered.

Because state selection skips re-walking the common prefix (~line 5182), the identical frame’s per-depth entries in FramesStateSelectionEvents are never written and are empty. If that frame contains two or more active states with “Event Required to Enter”: the first empty entry takes the “steal” branch and adds an invalid FStateTreeSharedEvent to EventsInUse (~2546); the second empty entry then matches it (two null TSharedPtrs compare equal), takes the copy branch, and EventToCapture (~2541) trips check(Event.IsValid()) in FStateTreeSharedEvent::operator (StateTreeEvents.h:119).

Side effect even with a single required-event state: the steal branch overwrites the state’s stored captured event with the empty one, which breaks event-payload bindings and fires the ensure(SharedEvent.IsValid()) in StateTreeInstanceData.cpp:284 on the next read.

What Type of Bug are you experiencing?

AI

Steps to Reproduce

  1. Create a StateTree sub-asset ST_Sub (Component schema) with two sibling child states A and B; give A a Delay task and an On State Completed → B transition.
  2. Create a main StateTree: under Root, a state P1 with Event Required to Enter (tag Test.Event, any payload struct), and its child P2 as a Linked Asset state pointing at ST_Sub, also with Event Required
    to Enter Test.Event (both with “Consume Event On Select” off).
  3. Add a transition into P1 on event Test.Event, run the tree on a StateTreeComponent, send the event.
  4. When A’s delay completes and the internal A → B transition fires inside the linked frame, the assert hits.

Expected Result

I can transition states without a crash

Observed Result

Unreal Crashes

Affects Versions

5.6

Platform(s)

Windows

This should be fixed in 5.8. I know we added functionality to support similar cases where a child state could be selected while keeping the state with a required event in a sustained transition. What you are describing reminds me very much of the use case we were solving with the fix. If you would like, I can track down the GitHub commit if you want to cherrypick or manually add the change yourself to 5.6. There may be some other work also needed since it is from 2 versions later.

-James