Blueprints
Common mistakes when you build Blueprints with MifBridge: variable defaults, function and event flags, pins, nodes, structs and enums, widget layout and compiles. Each entry says what you see, why, and what to do instead.
Call grammar and type names are on mistakes-calling. What ok:false does not undo is on mistakes-losing-work.
Variables
set_variable_flags is a partial update
Only the keys you send change. The keys, also accepted by add_variable:
replicated · repNotify · repNotifyFunction · replicationCondition
saveGame · transient · config
instanceEditable · blueprintReadOnly · exposeOnSpawn · advancedDisplay · interp · deprecated
category · tooltip
Member variables only. A local variable lives for one call and is never replicated or saved. Asking for these flags on a local is an explicit error.
repNotifyorrepNotifyFunctionimpliesreplicatedand creates theOnRep_<Var>function graph if it does not exist, because the compiler errors without it. The answer reportscreatedRepNotifyGraph.replicationConditiontakes a lifetime condition such asCOND_OwnerOnly,COND_SkipOwnerorCOND_InitialOnly. TheCOND_prefix is optional.A replicated variable does nothing unless the owning actor replicates. If
bReplicatesis false, the answer carriesreplicationWarning. The bridge does not flip it for you:{ "objectPath": "/Game/BP/BP_Vehicle.Default__BP_Vehicle_C", "propertyPath": "bReplicates", "value": "True" }exposeOnSpawnimpliesinstanceEditable.list_variablesreports the currentflagsof every variable, so you can verify a change without opening the Details panel.
Where a variable's default lives
What you see: list_variables shows no default for a variable you know has one, or set_variable_default answers differently than you expect.
Why: after a compile, the default is stored on the class default object, and the copy on the variable itself is emptied. The Blueprint editor's own Default Value field edits the class default object for the same reason. list_variables reads the right place, and tells you which one it read:
list_variables row |
Means |
|---|---|
default and defaultSource: "classDefaultObject" |
The class default object's value, in the same form get_property returns |
default and defaultSource: "variableDescription" with compiled: false |
The class does not hold the variable yet (added, renamed or retyped since the last compile). This is the text set on the variable, which the next compile applies |
compiled: false and no default |
Not compiled, and nothing set |
pendingDefault |
A default set since the last compile that differs from the class's. default stays the class's value until the compile replaces it |
A response with a compiled: false row or a pendingDefault carries a defaultNote.
- A retyped variable is
compiled: falseuntil the next compile.set_variable_typedoes not compile, and the class keeps the old kind. The row shows no default rather than a float's text under an int type. - "Differs" is by value.
"true"and"True"are the same, and so are"()"and an empty array. Object references are compared as text only, because parsing one can load a package. valueBeforeandvalueAfterinset_variable_defaultare the default as the next compile will apply it. Sending the value the class already holds answerschanged:falseand writes nothing.- An empty default cannot be written to a compiled variable this way.
value:nullor""is refused there, and the refusal names the two routes that work: send the value you want, or useset_propertyon the class default object. On a variable that is not compiled yet,nullstill clears it.
Functions and events
set_function_flags
Target a function graph or a custom event by nodeGuid (custom event), graphId, or blueprintId plus function.
replicates: none | multicast | server | client reliable
access: public | protected | private pure · const · callInEditor
category · tooltip · keywords
It is a partial update, like the variable flags. Things worth knowing:
- A replication change triggers a full compile. Other Blueprints that call the function keep stale call-site bytecode until they are compiled too. A skeleton regeneration is not enough.
- An overriding custom event is refused. Its network flags come from the parent, which is why the editor greys the row out. Change them on the class that declares the event.
pureandconstapply to function graphs only.- UE 5.3's function graph Details panel has no Replicates row at all.
set_function_flagson a function graph sets something the editor hides there. The flags are real and the compiler honors them, but you cannot verify them by clicking. - You get warnings, not errors, for an RPC on a non-replicated actor,
reliablewithoutreplicates, andpurecombined with an RPC. The compiler does not reject that last one. It zeroes the return value whenever the call runs remotely.
Making an event an RPC renames it
What you see: after replicates: "multicast", a lookup of the event by name finds nothing.
Why: the engine prefixes the name to match the RPC convention. A custom event called MulticastBoom comes back as Multicast_MulticastBoom. Run on Server and Run on owning Client prefix similarly. The node GUID is stable, but anything that holds the old name goes stale: a find_nodes by title, a set_function_flags addressed by function, a call site addressed by name.
Do instead: address the event by nodeGuid after changing its replication, and read the returned target to learn the new name.
Compile-heavy calls run alone
A full compile reinstances the class, and an undo over that would restore a dead default object. So compile-heavy endpoints run outside the blanket transaction, and batch refuses to nest them. Do not copy a list of them from a page. self_audit reports the live set as transactionBuckets.compileHeavy.
Pins and nodes
Choosing the node class: array functions
add_function_call picks the same node class the engine would for a given function and reports it as nodeClass:
| Function metadata | Node class |
|---|---|
Array library functions (MD_ArrayParam) |
UK2Node_CallArrayFunction |
| Data table pin functions | UK2Node_CallDataTableFunction |
| Commutative and pure | UK2Node_CommutativeAssociativeBinaryOperator |
| Material parameter collection functions | UK2Node_CallMaterialParameterCollectionFunction |
Interface function on an external target (or asMessage: true) |
UK2Node_Message |
Array Add, Remove, Contains, Length, Find, Insert, Append and Sort are directly authorable. You do not need a ForEach loop as a workaround. refresh_node reproduces a reload, so it remains the way to prove a node stays typed before you cook.
The engine's type-promotion operator node is deliberately not selected: spawned outside the editor's own path it comes up with unresolved wildcards.
add_pin: input and output are in function terms
add_pin takes name, type, optional direction, container and default, plus a target (graphId, blueprintId with function, or nodeGuid for a custom event). You say input or output as a caller of the function would. If you ever inspect the nodes directly, a function's inputs live on the entry node as output pins, and its outputs live on the Return node as input pins, which is why the directions look backward there.
- A custom event has no outputs.
direction: "output"is refused. - Adding an output to a function with no Return node creates the Return node and wires it from the entry's exec. Without that link the out-parameter is never written and the value feeding it is dropped, so it compiles clean and does nothing.
- Outputs are mirrored onto every Return node in the graph under the same name, because all of them share one signature.
- The name is made unique if taken. The answer reports the final name and a
warningwhen it differs from the one you asked for. - An illegal type or direction fails before anything changes.
remove_pin handles two cases
remove_pin takes node, pin, confirm: true and optional direction:
kind |
What |
|---|---|
userDefined |
A function input or output, a custom event parameter or a tunnel pin: the Details panel X button. It removes the live pin and its stored record, then syncs sibling Return nodes |
duplicate |
Two pins share a name and direction. Keeps a wired copy and drops the twin |
Anything else is refused. Engine-allocated pins are recreated on the next reconstruct, so removing one would silently revert.
A wildcard node needs refresh_node before you read it
What you see: you connect an enum to a Select node's Index pin, read the node back, and it still shows the generic Option 0, Option 1. It looks as if the enum form of Select is not reachable.
Why: the node reconfigures its pins when it is reconstructed, not when the connection is made.
Do instead: connect, then call refresh_node with the graph and node, then read. Options become one pin per enumerator. The same applies to any node that resolves pin types or pin count from what is attached to it. Reading first and concluding "it did not work" is a convincing false negative.
Wiring: connect_pins appends, reconnect_pin replaces
What you see: a 12-connection rewire answers 12/12 OK, and a read-back shows eight destinations carrying both the old and the new source.
Why: an object self pin can legally take more than one source. The engine appends rather than replaces when the destination is already linked and the callee has no return value, is impure and is not latent. That expands one call across several targets. A self pin on a function with a return value replaces instead. Two identical-looking pins, opposite results.
Do instead:
connect_pinsconnects without breaking what is there.reconnect_pinbreaks the existing link first. For replace semantics from one call, usereconnect_pin.- In
apply_graph_patch,existingLinkPolicydefaults toreplace.preserveopts into multi-target andrejectrefuses and names what is in the way. Each connect result carriessourcesBefore,sourcesAfter,replacedExistingandappendedToExisting. - Exec inputs are exempt. Several exec outputs may converge on one exec input, which is ordinary fan-in.
Other things a connect does that surprise people:
- It breaks existing links on a single-link pin.
- It wipes the destination input pin's default value.
- An automatic conversion node or a type promotion can be inserted.
apply_graph_patchrefuses those, because neither can be undone. - A wildcard pin passes a compatibility check against any type, and the first connect resolves it. A later connect in the same patch can become illegal. The endpoint checks again at apply time and reports
rollbackComplete:falseandrollbackReshapedNodesinstead of claiming a clean rollback it did not achieve.
Macros live in more than one library
What you see: add_macro_instance refuses SwitchHasAuthority and Switch Has Authority, and it looks as if the node does not exist.
Why: macroPath defaults to the standard macro library, which holds ForEachLoop, DoOnce, Gate, FlipFlop, IsValid and similar. Switch Has Authority is in the actor macro libraries, and a name that exists in several is not interchangeable between an actor and an actor component. Macro graph names can contain spaces (Do N, Create and Assign MID), so guessing the internal name by removing them is wrong.
Do instead:
- Copy the
macroblock thatlist_nodesandget_nodereturn for any existing macro instance.addMacroInstanceArgsholds the exactmacroGraphandmacroPath. - A miss lists
availableMacroGraphsanddidYouMean, and searches every macro library the asset registry knows, including your project's.foundInOtherLibrarynames eachmacroPathto retry with. - Matching ignores case and spacing, and the answer says
matchedBy: "normalized"when it was not an exact hit.
Binding a dispatcher on another class
add_bind_dispatcher binds an external dispatcher when you pass targetClass, which names the class that declares the dispatcher, not an object. Then connect the object to the node's Target pin with connect_pins:
add_bind_dispatcher(graph_id, "PlayerLoggedChanged", target_class="BP_MyGameMode")
connect_pins(cast_node, "AsBPMyGameMode", bind_node, "self")
Without targetClass it looks only on the Blueprint itself and answers that the dispatcher was not found. describe_class reads the dispatcher's parameter list.
Structs and enums
Applies to create_struct, add_struct_member, remove_struct_member, list_struct_members, create_enum, add_enum_value, remove_enum_value and list_enum_values.
- Blueprint types only. Native C++ structs and enums are refused with that reason.
- A struct member's real name is not what you typed. The engine appends a GUID suffix, and the name you see in the editor is a separate friendly name.
list_struct_membersreturns each member's GUID, the only stable handle across the recompile every edit triggers.remove_struct_memberaccepts a name or a GUID. - An enum entry's internal name is generated. The text you give
create_enumoradd_enum_valuebecomes the display name, which is what Blueprint shows andlist_enum_valuesreports. - Both keep at least one member. Removing the last one is refused. A new struct ships with a placeholder member that is dropped once your own members exist.
- Removing a non-final enum entry shifts every later index down. Anything that stored the enum by index, such as switch-on-enum nodes or saved defaults, silently points at a different value. The answer warns when this happens. Refresh affected switch nodes afterward.
UMG widget layout
add_tree_widget places a widget. All of its layout is set_property on the widget template, using blueprintId plus widgetName:
{ "blueprintId": "/Game/UI/WBP_HUD.WBP_HUD", "widgetName": "HealthBar",
"propertyPath": "Slot.Anchors.Minimum", "value": "(X=0.5,Y=0.0)" }
Slot.* covers anchors, alignment, offsets, size rules and z-order. The slot class depends on the parent panel, so list_object_properties on the widget shows what its slot exposes. Styles, brushes, fonts, colors and padding are ordinary properties on the widget.
Costs to know:
- The widget branch of
set_propertyruns a full compile on every write, so four properties are four compiles. - That branch cannot be put inside
batch. It refuses itself there, because a compile inside the batch's transaction would leave a dead default object for the next undo. - The
objectPathbranch (class defaults, component templates, node properties, placed actors) compiles nothing and can be batched.
Where to go next
- mistakes-calling for parameter names and strict values
- mistakes-losing-work for undo, batch and rollback limits
- mistakes-cooked-projects when the Blueprint is cooked
- mistakes-animation for Animation Blueprints