egametang/ET · error · Exception

condition node field not found: {node.GetType().FullName}.{f

Error message

condition node field not found: {node.GetType().FullName}.{fieldName}

What it means

Thrown by SetCompareField when reflecting a custom (non-BTNumericCompare) condition node for one of the shared compare fields (Op / Value / ErrorCode). The node type was registered via [ConditionVariable] and selected by ParseCompare, but it does not declare a public instance field with that exact name, so GetField returns null.

Source

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

                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)
            {
                throw new Exception($"condition node owner key field not found: {node.GetType().FullName}.{nameof(BTNumericCompare.OwnerKey)}");
            }

            if (fieldInfo.FieldType != typeof(string))
            {
                throw new Exception($"condition node owner key field must be string: {node.GetType().FullName}.{nameof(BTNumericCompare.OwnerKey)}");
            }

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Add a public instance field with the exact name reported in the message (Op of type ConditionCompareOp, Value matching the numeric type, ErrorCode of type int) to the custom node class.
  2. Use a plain public field, not an auto-property; GetField with Instance|Public will not see properties.
  3. If you intended a BTN-style node, consider inheriting BTNumericCompare so the fields come for free.

Example fix

// before
[ConditionVariable("MyFlag")]
public class MyFlagNode : BTCondition
{
    public int Threshold; // wrong name
}
// after
[ConditionVariable("MyFlag")]
public class MyFlagNode : BTCondition
{
    public ConditionCompareOp Op;
    public long Value;
    public int ErrorCode;
}
Defensive patterns

Strategy: type-guard

Type guard

// verify a custom condition node declares the required public fields
static bool HasCompareFields(Type t) =>
    t.GetField("Op", BindingFlags.Instance | BindingFlags.Public) != null
    && t.GetField("Value", BindingFlags.Instance | BindingFlags.Public) != null
    && t.GetField("ErrorCode", BindingFlags.Instance | BindingFlags.Public) != null;

Prevention

When it happens

Trigger: Registering a custom [ConditionVariable] node that omits or renames the public `Op`, `Value`, or `ErrorCode` field; declaring the field as a property instead of a field; marking it private/protected; or declaring it on a base class that is not visible to Instance|Public binding on the concrete type.

Common situations: A developer adds a new condition variable type and forgets the canonical field set; a rename refactor changes `Value` to `Threshold` without updating expectations; field is auto-property (backing field is private and compiler-named).

Related errors


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