Bug: level.load_level asserts in TickTaskManager and kills the editor
Unlike #65 this is not malformed input — it is a plain, documented call with a valid map path.
Environment
- Engine: UE 5.8.0, CL
55116800, ++UE5+Release-5.8
- Plugin: UnrealMCPython 2.2.0
- OS: Windows 11
Repro
With the editor open on some other map, call:
les = unreal.get_editor_subsystem(unreal.LevelEditorSubsystem)
les.load_level('/Game/<YourProject>/Maps/<SomeMap>')
…via util.execute_python (or the equivalent level.load_level action). The client sees
ConnectionResetError [WinError 10054] and the editor process is gone.
Crash
Assertion failed: !LevelList.Contains(TickTaskLevel)
[File: .../Engine/Source/Runtime/Engine/Private/TickTaskManager.cpp] [Line: 1992]
Analysis
The level load is being driven from inside the TCP server's game-thread dispatch, mid-frame,
while the previous level's tick task registration is still live — so the new level's
TickTaskLevel is added while the old one is still in LevelList and the assert fires.
This looks related to a broader pattern in the same dispatch path. Across a day of driving
this plugin I collected 18 crash reports, and every one has UnrealMCPython or
PythonScriptPlugin frames in the stack. Seven of them are:
Ensure condition failed: IsInGameThread()
[File: .../Runtime/Core/Private/Misc/AppTime.cpp] [Line: 38]
Attempted to retrieve FAppTime on a thread where there is no inherited time context.
Those are non-fatal, but they say plainly that engine state is being touched off the game
thread (or on a task with no inherited context). The load_level assert looks like the same
root cause reaching something that is checked rather than ensured.
Workaround
Do not load levels through the bridge. Launch the editor with the map on the command line
instead, which is reliable:
UnrealEditor.exe <Project>.uproject /Game/<Project>/Maps/<SomeMap>
Suggested fix
Defer level loading to a safe point in the frame (next tick / FCoreDelegates post-tick)
rather than executing it inline in the socket dispatch, and generally ensure the dispatch path
runs with an inherited time context so the IsInGameThread ensures stop firing.
Bug:
level.load_levelasserts in TickTaskManager and kills the editorUnlike #65 this is not malformed input — it is a plain, documented call with a valid map path.
Environment
55116800,++UE5+Release-5.8Repro
With the editor open on some other map, call:
…via
util.execute_python(or the equivalentlevel.load_levelaction). The client seesConnectionResetError [WinError 10054]and the editor process is gone.Crash
Analysis
The level load is being driven from inside the TCP server's game-thread dispatch, mid-frame,
while the previous level's tick task registration is still live — so the new level's
TickTaskLevelis added while the old one is still inLevelListand the assert fires.This looks related to a broader pattern in the same dispatch path. Across a day of driving
this plugin I collected 18 crash reports, and every one has
UnrealMCPythonorPythonScriptPluginframes in the stack. Seven of them are:Those are non-fatal, but they say plainly that engine state is being touched off the game
thread (or on a task with no inherited context). The
load_levelassert looks like the sameroot cause reaching something that is checked rather than ensured.
Workaround
Do not load levels through the bridge. Launch the editor with the map on the command line
instead, which is reliable:
Suggested fix
Defer level loading to a safe point in the frame (next tick /
FCoreDelegatespost-tick)rather than executing it inline in the socket dispatch, and generally ensure the dispatch path
runs with an inherited time context so the
IsInGameThreadensures stop firing.