In an nDisplay context, we have a project with a nDisplay Root Actor. In order to do the correct initialization sequence in all our modules and subsystems, we have added two explicit parameters -corailPrimary and -corailSecondary in order to enable/disable some of our code depending on primary/secondary node.
We have tested each initialization sequence with:
UnrealEditor-Win64-DebugGame.exe CorailKit.uproject -skipcompile -game /Unr/Maps/L_CorailKit_Showcase.L_CorailKit_Showcase -corailPrimary
and
UnrealEditor-Win64-DebugGame.exe CorailKit.uproject -skipcompile -game /Unr/Maps/L_CorailKit_Showcase.L_CorailKit_Showcase -corailSecondary
Both of them launch correctly.
But when I launch the same level, as primary, in the nDisplay context with Switchboard with the command line:
UnrealEditor-Win64-DebugGame.exe D:\CORAIL\Workspaces\megy-dev.unreal-local\UnrealData\CorailKit\CorailKit.uproject -game /Game/CompiledLevels/Linux_2025-04-11-17-01/L_Linux_2025-04-11-17-01 -messaging -dc_cluster -nosplash -fixedseed -NoVerifyGC -noxrstereo -xrtrackingonly -RemoteControlIsHeadless -corailPrimary -StageFriendlyName=node_front -MaxGPUCount=2 -dc_cfg=C:\Users\megy\AppData\Local\Temp\ndisplay\3796C10045B0A5647AE3CC8BA576EFCF.ndisplay -dx12 -dc_dev_mono -nosound -NoLoadingScreen -DisablePython -dc_node=node_front Log=node_front.log -ini:Engine:[/Script/Engine.Engine]:GameEngine=/Script/DisplayCluster.DisplayClusterGameEngine,[/Script/Engine.Engine]:GameViewportClientClassName=/Script/DisplayCluster.DisplayClusterViewportClient,[/Script/Engine.UserInterfaceSettings]:bAllowHighDPIInGameMode=True -ini:Game:[/Script/EngineSettings.GeneralProjectSettings]:bUseBorderlessWindow=True -ini:Input:[/Script/Engine.InputSettings]:DefaultPlayerInputClass=/Script/DisplayCluster.DisplayClusterPlayerInput -unattended -NoScreenMessages -handleensurepercent=0 -UDPMESSAGING_TRANSPORT_MULTICAST=230.0.0.1:6666 -UDPMESSAGING_TRANSPORT_UNICAST=127.0.0.1:0 -UDPMESSAGING_TRANSPORT_STATIC=127.0.0.1:9030 -ExecCmds=DisableAllScreenMessages -windowed -forceres WinX=640 WinY=0 ResX=607 ResY=1080 -CONCERTRETRYAUTOCONNECTONERROR -CONCERTAUTOCONNECT -CONCERTSERVER=“CORYS Local_MU_Server_Z6rbx5k3poEP” -CONCERTSESSION=MU_CORYS_Local_1 -CONCERTDISPLAYNAME=node_front -CONCERTISHEADLESS -DPCVars=Slate.bAllowNotifications=0,p.Chaos.Solver.Deterministic=1,LevelInstance.ForceEditorWorldMode=1""
It crash with a “Error: Assertion failed: GEditor” in the attached log.
Stephane,
Hi [mention removed]
The issue you have looks like that it is coming from your team code when trying to access the UActorEditorContextSubsystem by using the UActorEditorContextSubsystem* UActorEditorContextSubsystem::Get() call.
Switchboard launches Unreal Engine in Game mode, not the Editor. Probably, due to the -corailPrimary or -corailSeconday, these calls are going through a code logic that ends up calling the editor only functions.
I would work this issue by adding some GEditor checks that won’t crash in contexts that are not editor:
if (GIsEditor && GEditor) { // Safe to use GEditor }
So yes, the crash is a expected behavior if there is no safe guarding. I would separate the code logic into two branches:
- One for Editor context
- And one for Game/headless context (used by the switchboard).
Let me know if you need any help with the code.
Best,
Joan
The fact is that the crash happened in UActorEditorContextSubsystem::Get and the whole call stack (see attachement log) is inside the engine without any mention of our code from top to bottom of the call stack.
So :
- a safe guard fix must done in the engine somewhere in the call stack
- some modules dependencies may cause this behaviour
- ???
Hi [mention removed],
You are right, I’ll reproduce this issue locally and I’ll report the issue to Epic as this should not be happening. I’ll update shortly.
Best,
Joan
Hi [mention removed],
When UDataLayerManager::Initialize() runs during a Switchboard launch, it first attempts to locate an existing AWorldDataLayers actor in the selected World Partition level. In my case this is valid, and I do belive that it is not in you environment following the call stack.
`AWorldDataLayers* WorldDataLayers = GetWorldDataLayers();
if (!WorldDataLayers)
{
if (ActorDescContainerInstance)
{
// Try to find and load AWorldDataLayers actor
WorldDataLayersActor = UDataLayerManager::LoadWorldDataLayersActor(ActorDescContainerInstance);
}
WorldDataLayers = GetWorldDataLayers();
if (!WorldDataLayers)
{
// Create missing AWorldDataLayers actor
AWorldDataLayers* NewWorldDataLayers = AWorldDataLayers::Create(OuterWorld);
OuterWorld->SetWorldDataLayers(NewWorldDataLayers);
WorldDataLayers = GetWorldDataLayers();
check(WorldDataLayers);
}
}`
In my environment, this actor is present, so GetWorldDataLayers() returns a valid pointer and the initialization proceeds normally. Could you please confirm whether your level includes this actor (AWorldDataLayers)? If your project was upgraded from an earlier Unreal Engine version, there may have been migration issues where this actor was not properly recognized. If you don’t, try to instance one on the level.
If the actor is already present, it suggests there may be other configuration or migration issues that I am not currently reproducing. In that case, it would be extremely helpful if you could share a minimal reproduce case or sample project that Epic Support could test.
Best,
Joan