AI-assisted bug report. Let me know if the .dmp file is needed.
Bug: add_blueprint_node with type: "SpawnActor" crashes the Unreal Editor process
Environment
- Engine: UE 5.8.1-56057345+++UE5+Release-5.8
- Plugin:
genorca-unreal-mcp (MCP server for Unreal, MCPython TCP bridge on 127.0.0.1:12029)
- Project: blank/default project state, no special config
Summary
Calling the blueprint tool's add_blueprint_node action with node_json.type = "SpawnActor" kills the Unreal Editor process outright. The MCP client sees the TCP connection drop (WinError 10054), and the editor is gone — not just a failed call, the whole process. Reproduced 4 times across 2 different target assets (including a blueprint created fresh immediately beforehand, with zero prior state), and with zero parameters beyond the type itself, so it is not caused by any particular argument value, accumulated graph/compile state, or blueprint class.
Precondition
Editor running with the MCPython TCP server active and responding normally (confirmed via a working util.get_project_info call immediately beforehand each time).
Steps to reproduce (minimal, isolated case)
- Create a brand-new, untouched Blueprint via
blueprint.create_blueprint:
{ "action": "create_blueprint", "params": { "asset_path": "/Game/BugRepro_SpawnActorTest", "parent_class_path": "/Script/Engine.Actor" } }
- Immediately call
add_blueprint_node on its EventGraph with the type and nothing else:
{
"action": "add_blueprint_node",
"params": {
"asset_path": "/Game/BugRepro_SpawnActorTest.BugRepro_SpawnActorTest",
"graph_name": "EventGraph",
"node_json": { "type": "SpawnActor" }
}
}
- Observe the response.
This is deliberately the smallest possible case: a blueprint with no prior nodes, no variables, no components, no compile history — created and crashed in the same two calls, nothing else touched in between.
Actual result
{
"success": false,
"message": "Socket error (127.0.0.1:12029): [WinError 10054] An existing connection was forcibly closed by the remote host",
"details": { "host": "127.0.0.1", "port": 12029 }
}
A follow-up call (util.get_project_info, no other params) immediately after returns:
{ "success": false, "message": "Connection refused (127.0.0.1:12029). Ensure Unreal MCPython TCP server is active." }
confirming the editor process itself has terminated, not just the one request failing. The Windows Event Log / editor crash reporter should have a corresponding UE crash entry timestamped to the call in step 2.
Expected result
Either a successfully created SpawnActor node, or — if the node type is unsupported/misconfigured in some way — a normal {"success": false, "message": "..."} validation response, same as every other malformed request this plugin handles (e.g. unknown node types normally return "Unknown node type 'X'. Supported: ..." without crashing anything).
Reproduction attempts (all crashed identically)
| Attempt |
Target asset |
node_json payload |
Result |
| 1 |
/Game/WBP_ModuleEditor.WBP_ModuleEditor (widget BP, pre-existing widget tree + prior node/compile churn) |
{"type":"SpawnActor","class_path":"/Game/BP_Module_A.BP_Module_A_C","pos_x":0,"pos_y":1200} |
Crash |
| 2 |
Same asset, retried after editor restart |
Identical to #1 |
Crash (identical error) |
| 3 |
Same asset |
{"type":"SpawnActor"} — no other keys at all |
Crash (identical error) |
| 4 |
/Game/BugRepro_SpawnActorTest.BugRepro_SpawnActorTest — freshly created via create_blueprint, zero prior nodes/variables/components/compiles |
{"type":"SpawnActor"} |
Crash (identical error) |
Attempts #1–3 rule out class_path value/format and position args as the trigger — the crash fires regardless of what's passed alongside the type. Attempt #4 additionally rules out the target asset: it isolates a plain, brand-new Actor blueprint created and crashed in two calls total, with no accumulated graph state, no widget tree, and not even the same Blueprint class (Actor vs. the original EditorUtilityWidget). The crash reproduces identically. This confirms the trigger is the SpawnActor node type itself in add_blueprint_node, independent of target asset, blueprint class, graph history, and parameters.
Confirmed root cause (from the actual crash dump, not just source reading)
The reproduction on the fresh BugRepro_SpawnActorTest blueprint produced a full crash dump with debug symbols. This is a deliberate fatal assertion, not memory corruption or an unhandled exception:
Assertion failed: Result [File:...\Engine\Source\Runtime\Engine\Classes\EdGraph\EdGraphNode.h] [Line: 586]
That's UEdGraphNode::FindPinChecked():
// EdGraphNode.h:583-588
UEdGraphPin* FindPinChecked(const FName PinName, const EEdGraphPinDirection Direction = EGPD_MAX) const
{
UEdGraphPin* Result = FindPin(PinName, Direction);
check(Result); // <-- fires here: the requested pin does not exist
return Result;
}
Something in UK2Node_SpawnActorFromClass's pin-setup path (or its base UK2Node_ConstructObjectFromClass) looks up a pin by name that isn't there yet, and the engine intentionally halts rather than proceed with a null pin — this is UE's own safety net catching a real invariant violation, not an obscure edge case.
Full call stack (from CrashContext.runtime-xml), confirming exactly where in the plugin this originates:
UnrealEditor_Core <- assert handler
UnrealEditor_BlueprintGraph <- inside SpawnActorFromClass/ConstructObjectFromClass pin logic
UnrealEditor_BlueprintGraph
UnrealMCPython!CreateBPNodeFromJson() [MCPythonHelper.cpp:648] <- Creator.Finalize(); (triggers AllocateDefaultPins)
UnrealMCPython!UMCPythonHelper::AddBlueprintNode() [MCPythonHelper.cpp:696]
UnrealMCPython!execAddBlueprintNode() [MCPythonHelper.gen.cpp:599]
... python311 / PythonScriptPlugin bridge frames ...
UnrealMCPython!FMCPythonTcpServer::ProcessDataOnGameThread() [MCPythonTcpServer.cpp:374]
Line 648 is exactly the Creator.Finalize(); call in the SpawnActor branch shown above — confirming the crash is inside pin allocation for this node class specifically, not in node construction, the TCP server, or the Python bridge layers above it.
Static reading of UK2Node_SpawnActorFromClass::AllocateDefaultPins() and UK2Node_ConstructObjectFromClass::AllocateDefaultPins() (both in Engine source) shows only pin-creation calls, not the failing FindPinChecked — so the actual call site is one level deeper (a helper or notify hook invoked from there) and is best found with a debugger rather than more source reading.
Attaching the crash dump directly (recommended)
This reproduction generated a full dump with debug symbols at:
E:\UE5\MachineLearning\Saved\Crashes\UECC-Windows-F26E4EFD47DB3038E7F99789C157F69F_0000\
UEMinidump.dmp
CrashContext.runtime-xml
MachineLearning.log
Opening UEMinidump.dmp in Visual Studio (with matching 5.8.1-56057345 engine symbols) will show the exact line inside AllocateDefaultPins() that calls the failing FindPinChecked, in seconds — hand the whole folder to the developer rather than relying on this write-up alone.
Root cause investigation (source-level, MCPythonHelper.cpp)
Checked against the plugin's own source (Plugins/UnrealMCPython/Source/UnrealMCPython/Private/MCPythonHelper.cpp) rather than guessing from docs. The "SpawnActor" node type is not a stale/removed API reference — it correctly targets UK2Node_SpawnActorFromClass, the same class behind "Spawn Actor from Class" in the editor's own node-picker menu, and the header (K2Node_SpawnActorFromClass.h) compiles fine against this UE 5.8.1 build (the plugin builds and runs). So this isn't a version-mismatch issue.
The construction code (CreateBPNodeFromJson, ~line 642):
else if (NodeType == TEXT("SpawnActor"))
{
FGraphNodeCreator<UK2Node_SpawnActorFromClass> Creator(*Graph);
UK2Node_SpawnActorFromClass* SpawnNode = Creator.CreateNode(false);
SpawnNode->NodePosX = PosX;
SpawnNode->NodePosY = PosY;
Creator.Finalize();
NewNode = SpawnNode;
}
This exact pattern (FGraphNodeCreator<T> → CreateNode(false) → set position → Creator.Finalize()) is used identically for the MacroInstance, InputKey, and VariableSet branches elsewhere in the same function, and those do not crash in this session. That rules out the generic creation pattern as the cause and narrows it to something specific to UK2Node_SpawnActorFromClass — most likely inside its AllocateDefaultPins() override, which Creator.Finalize() triggers. Hypothesis: this node class may expect additional setup that the interactive Blueprint-editor node-spawner path performs before pin allocation (e.g. UBlueprintNodeSpawner-driven placement), which this direct FGraphNodeCreator construction skips — worth checking whether AllocateDefaultPins() dereferences something not yet valid at this point (e.g. a cached function signature, spawn-class default, or world-context lookup).
Suggested manual differential test (not yet performed by us — recommended for whoever picks this up): in the Blueprint editor UI, right-click an EventGraph, search "Spawn Actor from Class", and place it manually (unconnected, no compile). If that does not crash — which is expected, since it's a common, heavily-used node — it confirms the defect is specific to this plugin's direct-construction code path for that node class, not the node class or engine itself.
Notes for the developer
- Workaround in use on our end: spawning via
CallFunction targeting a GameplayStatics deferred-spawn function instead of the SpawnActor node type.
- Each reproduction required a manual editor restart before the next call would succeed — there's no way to recover the TCP session without relaunching Unreal.
AI-assisted bug report. Let me know if the .dmp file is needed.
Bug:
add_blueprint_nodewithtype: "SpawnActor"crashes the Unreal Editor processEnvironment
genorca-unreal-mcp(MCP server for Unreal, MCPython TCP bridge on127.0.0.1:12029)Summary
Calling the
blueprinttool'sadd_blueprint_nodeaction withnode_json.type = "SpawnActor"kills the Unreal Editor process outright. The MCP client sees the TCP connection drop (WinError 10054), and the editor is gone — not just a failed call, the whole process. Reproduced 4 times across 2 different target assets (including a blueprint created fresh immediately beforehand, with zero prior state), and with zero parameters beyond the type itself, so it is not caused by any particular argument value, accumulated graph/compile state, or blueprint class.Precondition
Editor running with the MCPython TCP server active and responding normally (confirmed via a working
util.get_project_infocall immediately beforehand each time).Steps to reproduce (minimal, isolated case)
blueprint.create_blueprint:{ "action": "create_blueprint", "params": { "asset_path": "/Game/BugRepro_SpawnActorTest", "parent_class_path": "/Script/Engine.Actor" } }add_blueprint_nodeon itsEventGraphwith the type and nothing else:{ "action": "add_blueprint_node", "params": { "asset_path": "/Game/BugRepro_SpawnActorTest.BugRepro_SpawnActorTest", "graph_name": "EventGraph", "node_json": { "type": "SpawnActor" } } }This is deliberately the smallest possible case: a blueprint with no prior nodes, no variables, no components, no compile history — created and crashed in the same two calls, nothing else touched in between.
Actual result
{ "success": false, "message": "Socket error (127.0.0.1:12029): [WinError 10054] An existing connection was forcibly closed by the remote host", "details": { "host": "127.0.0.1", "port": 12029 } }A follow-up call (
util.get_project_info, no other params) immediately after returns:{ "success": false, "message": "Connection refused (127.0.0.1:12029). Ensure Unreal MCPython TCP server is active." }confirming the editor process itself has terminated, not just the one request failing. The Windows Event Log / editor crash reporter should have a corresponding UE crash entry timestamped to the call in step 2.
Expected result
Either a successfully created
SpawnActornode, or — if the node type is unsupported/misconfigured in some way — a normal{"success": false, "message": "..."}validation response, same as every other malformed request this plugin handles (e.g. unknown node types normally return"Unknown node type 'X'. Supported: ..."without crashing anything).Reproduction attempts (all crashed identically)
node_jsonpayload/Game/WBP_ModuleEditor.WBP_ModuleEditor(widget BP, pre-existing widget tree + prior node/compile churn){"type":"SpawnActor","class_path":"/Game/BP_Module_A.BP_Module_A_C","pos_x":0,"pos_y":1200}{"type":"SpawnActor"}— no other keys at all/Game/BugRepro_SpawnActorTest.BugRepro_SpawnActorTest— freshly created viacreate_blueprint, zero prior nodes/variables/components/compiles{"type":"SpawnActor"}Attempts #1–3 rule out
class_pathvalue/format and position args as the trigger — the crash fires regardless of what's passed alongside the type. Attempt #4 additionally rules out the target asset: it isolates a plain, brand-newActorblueprint created and crashed in two calls total, with no accumulated graph state, no widget tree, and not even the same Blueprint class (Actorvs. the originalEditorUtilityWidget). The crash reproduces identically. This confirms the trigger is theSpawnActornode type itself inadd_blueprint_node, independent of target asset, blueprint class, graph history, and parameters.Confirmed root cause (from the actual crash dump, not just source reading)
The reproduction on the fresh
BugRepro_SpawnActorTestblueprint produced a full crash dump with debug symbols. This is a deliberate fatal assertion, not memory corruption or an unhandled exception:That's
UEdGraphNode::FindPinChecked():Something in
UK2Node_SpawnActorFromClass's pin-setup path (or its baseUK2Node_ConstructObjectFromClass) looks up a pin by name that isn't there yet, and the engine intentionally halts rather than proceed with a null pin — this is UE's own safety net catching a real invariant violation, not an obscure edge case.Full call stack (from
CrashContext.runtime-xml), confirming exactly where in the plugin this originates:Line 648 is exactly the
Creator.Finalize();call in theSpawnActorbranch shown above — confirming the crash is inside pin allocation for this node class specifically, not in node construction, the TCP server, or the Python bridge layers above it.Static reading of
UK2Node_SpawnActorFromClass::AllocateDefaultPins()andUK2Node_ConstructObjectFromClass::AllocateDefaultPins()(both in Engine source) shows only pin-creation calls, not the failingFindPinChecked— so the actual call site is one level deeper (a helper or notify hook invoked from there) and is best found with a debugger rather than more source reading.Attaching the crash dump directly (recommended)
This reproduction generated a full dump with debug symbols at:
Opening
UEMinidump.dmpin Visual Studio (with matching 5.8.1-56057345 engine symbols) will show the exact line insideAllocateDefaultPins()that calls the failingFindPinChecked, in seconds — hand the whole folder to the developer rather than relying on this write-up alone.Root cause investigation (source-level,
MCPythonHelper.cpp)Checked against the plugin's own source (
Plugins/UnrealMCPython/Source/UnrealMCPython/Private/MCPythonHelper.cpp) rather than guessing from docs. The"SpawnActor"node type is not a stale/removed API reference — it correctly targetsUK2Node_SpawnActorFromClass, the same class behind "Spawn Actor from Class" in the editor's own node-picker menu, and the header (K2Node_SpawnActorFromClass.h) compiles fine against this UE 5.8.1 build (the plugin builds and runs). So this isn't a version-mismatch issue.The construction code (
CreateBPNodeFromJson, ~line 642):This exact pattern (
FGraphNodeCreator<T>→CreateNode(false)→ set position →Creator.Finalize()) is used identically for theMacroInstance,InputKey, andVariableSetbranches elsewhere in the same function, and those do not crash in this session. That rules out the generic creation pattern as the cause and narrows it to something specific toUK2Node_SpawnActorFromClass— most likely inside itsAllocateDefaultPins()override, whichCreator.Finalize()triggers. Hypothesis: this node class may expect additional setup that the interactive Blueprint-editor node-spawner path performs before pin allocation (e.g.UBlueprintNodeSpawner-driven placement), which this directFGraphNodeCreatorconstruction skips — worth checking whetherAllocateDefaultPins()dereferences something not yet valid at this point (e.g. a cached function signature, spawn-class default, or world-context lookup).Suggested manual differential test (not yet performed by us — recommended for whoever picks this up): in the Blueprint editor UI, right-click an EventGraph, search "Spawn Actor from Class", and place it manually (unconnected, no compile). If that does not crash — which is expected, since it's a common, heavily-used node — it confirms the defect is specific to this plugin's direct-construction code path for that node class, not the node class or engine itself.
Notes for the developer
CallFunctiontargeting aGameplayStaticsdeferred-spawn function instead of theSpawnActornode type.