DUI2xxx · Parser
Tokens that do not form the grammar.
Generated by scripts/diagnostics/sync.py from the plugin's code table (EDreamUIDiagnosticCode); the name on each card is the one the tests assert.
DUI2001
errorcode nameUnexpectedToken
A token where the grammar wants something else; the message names both.
How it happens: the parser's general refusal: a name expected and something else found, nothing after ->, a for, an each or a slot at the top of the file, an annotation other than @key after a value, and so on. The message's "expected" half says what was missing.
for Item in GetItems() {
Text Cell { Text <- Item.Name }
}
Widget Root { }How to fix: write what the message expected; here, move the loop inside a node.
DUI2002
errorcode nameUnclosedBlock
A { with no matching }.
How it happens: the blocks of nodes, style, resources, props, events, timeline and rows all close. The diagnostic points at the opening brace rather than the end of the file, because "the file ended here" is the least useful true thing a parser can say.
Widget Root {
Text Title {
Text = "Settings"
}How to fix: add the } where the reported { should close; the editor's folding and bracket highlighting find it.
DUI2003
errorcode nameUnclosedTuple
A ( with no matching ).
How it happens: a tuple value (a vector, a margin, a rotator) may span lines, so the parser looks on for its ); reaching a } or the end of the file first is this code, and the search stops there instead of eating the rest of the enclosing node. An unclosed parenthesis in a binding expression is DUI2011.
Text Label {
@slot Padding = (0, 4, 0, 4
}How to fix: add the ).
DUI2004
errorcode nameMissingNodeId
A node with neither an id nor a block, or an unnamed node with (was: …).
How it happens: a node nothing refers to by name may leave its id out, as long as a block or a style clause follows the type (HorizontalBox { … }, Text : Caption). A type alone on a line (Text) is still an error: it is as likely a property whose = went missing. (was: …) renames a node, and a node with no id has nothing to be renamed to; it needs the new id written.
Widget Root {
Text
Text (was: Heading) { Text = "Settings" }
}How to fix: give the node an id (Text Title) or a block (Text { … }); if a property was meant, add its = value.
DUI2005
errorcode nameMissingPropertyValue
A property with no = or arrow, or nothing after it.
How it happens: a property line is Name = value, Name <- expression, Name <-> variable or Name -> Handler. A dotted name or a @slot line followed straight by a value, or an = with nothing after it before the end of the line, is this code.
Text Title {
FontSize =
AnchorData.SizeDelta (400, 240)
}How to fix: add the = and the value, or write <- Function().
DUI2006
errorcode nameMalformedRoot
No root node in a file compiled into a class, or more than one.
How it happens: a file compiled into a Blueprint has exactly one root node. A second one is reported where it stands (the first is kept), so you see which tree is the intruder. A file with no root is a library: it can be used and cannot be compiled, so a library set as a Blueprint's Source File gets "no root node".
Widget Root { }
Widget Footer { }How to fix: move the second tree into the first; if the file is a library, do not make it a Source File -- use it from another file.
DUI2007
errorcode nameMalformedClassDeclaration
class twice, with an empty path, or inside a node.
How it happens: class /Game/UI/WBP_Settings is a top-level statement, at most one per file: it says which Blueprint the file is the source of, and its path is the namespace of every localized string in the file.
class /Game/UI/WBP_Settings
class /Game/UI/WBP_Options
Widget Root { }How to fix: keep one class line, at the top level, followed by the full asset path.
DUI2008
errorcode nameMalformedWasClause
(was: …) holding something other than one id.
How it happens: a rename clause is (was: OldId), one identifier after the colon; empty, two words, or a string is this code.
Text Title (was: Old Title) { }How to fix: write (was: OldTitle), the id the node had before the rename.
DUI2009
errorcode nameMalformedKeyOverride
@key(…) holding something other than one string, or after a value that is not a string.
How it happens: @key("Dialog.Confirm") gives a string the key it is localized under. The parentheses hold exactly one non-empty quoted string, and the annotation follows only a quoted string, the one value that gets localized -- after a number it would be a setting that looks applied and does nothing.
Text Confirm {
Text = "OK" @key(Dialog.Confirm)
FontSize = 14 @key("Dialog.Size")
}How to fix: write Text = "OK" @key("Dialog.Confirm"); drop @key from a value that is not a string.
DUI2010
errorcode nameMalformedLoopHeader
A for / each header that is not <keyword> Var in Source or Source().
How it happens: a loop header is the keyword, the loop variable, in, and the source: a variable name (Options) or a call with no arguments (GetOptions()). A missing in, a source that is not a name, or arguments in the call is this code.
VerticalBox Options {
for Option GetOptions() {
Text { Text <- Option.Label }
}
}How to fix: write for Option in GetOptions(); a source that needs arguments becomes a no-argument function that passes them itself.
DUI2011
errorcode nameMalformedBindingExpression
The right side of <-, <-> or an emit's arguments that do not parse.
How it happens: the right side is a function call, a variable, a literal, or operators combining them. A stray token, an unclosed parenthesis or call, @ with no resource name, . with no member name, or <-> followed by something other than a variable name is this code. There is no / -- it belongs to paths and comments -- and no ? :.
Widget Panel {
RenderOpacity <- Fade() *
Shown <- (HasDetail()
}How to fix: complete the expression; put division and choices in a function and bind that.
DUI2012
errorcode nameImportFailed
A use that could not be honoured: no such file, unreadable, does not parse, or a cycle.
How it happens: use takes a quoted path, or a class path and as Name. A path with no readable file under any DUI/ root, an imported file with parse errors of its own, a file importing itself, or an import chain that comes back to a file already being imported is reported on the use line.
use "UI/Libary.dui"
Widget Root { }How to fix: check the spelling and which DUI/ root the path is relative to; when the imported file has errors, compile it directly to see them; break a cycle by moving what both share into a third file.
DUI2013
errorcode nameNestingTooDeep
Blocks or parentheses nested deeper than 256.
How it happens: a recursive-descent parser answers a file that nests a thousand deep by exhausting the stack, and a stack overflow is not a diagnostic -- it is the editor disappearing with the author's unsaved work. The limit is far above anything a hand-written or generated .dui reaches, so meeting it means a file that is malformed or hostile rather than merely deep; nothing below that level is read.
How to fix: check the tool that generated the file; a real screen splits deep structure into components.
DUI2014
errorcode nameMalformedTimeline
A timeline block or line that is not the grammar.
How it happens: one code for the whole block, with the message naming the part: a header with no name; external followed by a block, or neither a block nor external; duration or loop with no value, or a loop other than Once, Loop or PingPong; a track line with no :, or a node path with no property; a key with no =; a negative time; ease with no curve name; @time with no -> and event name.
timeline Pulse {
duration = 0.6
loop = Forever
Icon.RenderScale 0.0 = (1, 1, 1), 0.3 = (1.25, 1.25, 1)
}
Widget Root {
Image Icon
}How to fix: write the shapes the docs show: a track line is NodePath.Property : time = value ease Curve, …, an event key is @0.3 -> Landed.
DUI2015
errorcode nameMalformedUseDeclaration
use … as without a name, a keyword as the name, or a class path without as.
How it happens: the word after as is the whole name, so nothing may follow it, and a reserved keyword cannot be it. A class path such as use /Game/UI/WBP_Row has nothing to offer but the class, so without a name the line does nothing, and as is required.
use "UI/Components/Row.dui" as
use /Game/UI/WBP_Slider
Widget Root { }How to fix: write use "UI/Components/Row.dui" as Row, use /Game/UI/WBP_Slider as Slider.
DUI2016
errorcode nameMalformedPropsBlock
A props line that is not Type Name or Type Name = value, or props inside a node.
How it happens: a props block declares one property per line: a type, a name, and optionally = default, with an Enum type followed by the enum's path before the name. A missing name, an = with no value, or two names on one line is this code; so is a props block inside a node, since it declares what the file's class has and belongs at the top level.
props {
Text
Number Count =
}
Widget Root { }How to fix: write Text Label and Number Count = 0, and keep the props block at the top of the file.
DUI2017
errorcode nameMalformedEventsBlock
An events entry that is not Name or Name(Type Param, …), or events inside a node.
How it happens: each event is a name, optionally followed by a parenthesised parameter list of type-and-name pairs separated by , and closed by ); an entry ends at a line break or a ;. A parameter with no name, the wrong separator, something after the entry, or an events block inside a node is this code.
events {
Picked(Number)
}
Widget Root { }How to fix: write Picked(Number Index), and keep the events block at the top of the file.
DUI2018
errorcode nameMalformedConditional
An if without its condition or block, an else with no if, or a branch holding something other than widgets.
How it happens: if goes inside a node, followed by a binding expression as its condition and a { … } block; else is followed by a block, or by if and another condition. A branch holds widgets only: a property, a @slot line, a + block, a slot or a loop in one is this code, and so is an if at the top of the file. A widget in a branch cannot write Shown <-> either: the branch decides Shown, and a mirror would write that back into the variable.
Widget Root {
if HasSave() {
RenderOpacity = 0.5
Text Continue { Text = "Continue" }
}
}How to fix: put the property on a widget inside the branch; complete the condition or the block; put else on the line the } closed or on the next one.
DUI2019
errorcode nameMalformedSlotDeclaration
A slot with default twice, or a block that both declares and fills.
How it happens: slot Name { … } in a component file is a declaration -- its block holds components, properties and @slot lines that lay the hole out; slot Name { … } in a host is a fill -- its block holds widgets only. A block holding both, a fill carrying default, a style or (was: …), or a fill block with properties is this code.
Widget Root {
slot Footer default default
slot Detail {
+ VerticalBox { Spacing = 15 }
Text Note { Text = "A length of wire." }
}
}How to fix: keep widgets out of a declaration and everything else out of a fill; default, a style and a rename go on the declaration.
DUI2020
errorcode nameMalformedRows
A rows table that does not read: a column list that is not names, a column twice, a row with the wrong number of values.
How it happens: the header is rows Type : Style (Column, Column), the columns property names, each written once (compared without case, since two columns differing only in case name one property); each row's values match the columns one for one, separated by commas. A value too few means the author left something out, a value too many has nowhere to go -- both are guesses, so a row that does not read makes no widget.
VerticalBox Menu {
rows Text (Text, FontSize) {
"City Ruins", 18
"Desert Zone"
}
}How to fix: give every row as many values as there are columns; for what one row needs beyond the columns, end its line with a block.