egametang/ET · error · Exception

condition group error code only support leaf or not node: {n

Error message

condition group error code only support leaf or not node: {node.GetType().Name}

What it means

Thrown by ApplyErrorCode when the `:errorCode` suffix is attached to a parenthesized GROUP expression whose resulting node is neither a leaf compare nor a BTNot. The framework only knows how to push an ErrorCode onto BTNumericCompare / generic BTCondition (via field reflection) / BTNot, so applying it to a compound AND/OR node (which becomes BTSequence/BTSelector) is rejected.

Source

Thrown at Packages/cn.etetet.conditionexpr/Scripts/Model/Share/ConditionExprParser.cs:267

            if (node is BTNumericCompare numericCompare)
            {
                numericCompare.ErrorCode = errorCode;
                return;
            }

            if (node is BTCondition condition)
            {
                this.SetCompareField(condition, nameof(BTNumericCompare.ErrorCode), errorCode);
                return;
            }

            if (node is BTNot not)
            {
                not.ErrorCode = errorCode;
                return;
            }

            throw new Exception($"condition group error code only support leaf or not node: {node.GetType().Name}");
        }

        private void SetCompareField(BTCondition node, string fieldName, object value)
        {
            FieldInfo fieldInfo = node.GetType().GetField(fieldName, BindingFlags.Instance | BindingFlags.Public);
            if (fieldInfo == null)
            {
                throw new Exception($"condition node field not found: {node.GetType().FullName}.{fieldName}");
            }

            fieldInfo.SetValue(node, value);
        }

        private void SetOwnerKeyField(BTCondition node, string ownerKey)
        {
            FieldInfo fieldInfo = node.GetType().GetField(nameof(BTNumericCompare.OwnerKey), BindingFlags.Instance | BindingFlags.Public);
            if (fieldInfo == null)
            {

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Move the `:errorCode` onto each leaf compare inside the group instead of the group node, e.g. `(HP > 0:1000 && MP > 0:1000)`.
  2. If the whole group should share one code, wrap the group in a BTNot-free leaf or assign codes per leaf at design time.
  3. Document in the condition DSL that group-level error codes are unsupported except for `!leaf` (BTNot) forms.

Example fix

// before
(HP > 0 && MP > 0):1000
// after
(HP > 0:1000 && MP > 0:1000)
Defensive patterns

Strategy: validation

Validate before calling

// reject group-level error codes in the DSL before parsing
bool HasGroupErrorCode(string expr)
{
    // a ')' immediately followed (ignoring spaces) by ':' indicates a group-level code
    int close = expr.IndexOf(')');
    return close >= 0 && expr.Skip(close + 1).Any(c => !char.IsWhiteSpace(c)) && expr.IndexOf(':', close) == close + 1;
}

Prevention

When it happens

Trigger: Attaching an error code to a grouped boolean compound expression, e.g. `(HP > 0 && MP > 0):1000` (parenthesizing an AND yields a BTSequence) or `(A || B):5` (BTSelector). The colon-after-paren path at ParsePrimary line 95 calls ApplyErrorCode on that sequence/selector node.

Common situations: Designer wraps a sub-expression in parentheses to set a shared error code for the whole group, expecting the code to fan out to children; refactor that flattens a leaf into an AND without removing the `:code` suffix.

Related errors


AI-assisted analysis of egametang/ET@5cab01f7a8 (2026-08-13). Data as JSON: /api/errors/4dff3b8be9d40f31. Report an issue: GitHub.