egametang/ET · error · Exception

condition error code out of range: {token.Number}

Error message

condition error code out of range: {token.Number}

What it means

Thrown by ConditionExprParser.ReadErrorCode() while parsing the optional `:errorCode` suffix of a condition expression (e.g. `HP > 0:1000`). The Number token read after the colon is wider than int32, and the parser refuses to narrow it when it falls outside [int.MinValue, int.MaxValue]. This protects the downstream BTNumericCompare.ErrorCode field (an int) from silent truncation.

Source

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

            ++this.position;
            return token.Type switch
            {
                ConditionTokenType.Greater => ConditionCompareOp.Greater,
                ConditionTokenType.GreaterEqual => ConditionCompareOp.GreaterEqual,
                ConditionTokenType.Less => ConditionCompareOp.Less,
                ConditionTokenType.LessEqual => ConditionCompareOp.LessEqual,
                ConditionTokenType.Equal => ConditionCompareOp.Equal,
                ConditionTokenType.NotEqual => ConditionCompareOp.NotEqual,
                _ => throw new Exception($"condition compare op expected, actual: {token.Text}")
            };
        }

        private int ReadErrorCode()
        {
            ConditionToken token = this.Expect(ConditionTokenType.Number);
            if (token.Number < int.MinValue || token.Number > int.MaxValue)
            {
                throw new Exception($"condition error code out of range: {token.Number}");
            }

            return (int)token.Number;
        }

        private void ApplyErrorCode(BTNode node, int errorCode)
        {
            if (node is BTNumericCompare numericCompare)
            {
                numericCompare.ErrorCode = errorCode;
                return;
            }

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

View on GitHub (pinned to 5cab01f7a8)

Solutions

  1. Clamp the error code literal in the condition cell to the int32 range [-2147483648, 2147483647].
  2. If you genuinely need a wider code, extend ReadErrorCode and BTNumericCompare.ErrorCode to long on both parser and node sides, and regenerate Luban.
  3. Check the design table for the offending row using the reported token.Number value to locate it fast.

Example fix

// before (cell)
HP > 0:9999999999
// after
HP > 0:1000
Defensive patterns

Strategy: validation

Validate before calling

// before writing the cell / building the parser input
bool IsValidErrorCode(long code) => code >= int.MinValue && code <= int.MaxValue;
if (!tokens.Any(t => t.Type == ConditionTokenType.Colon)) return;
// validate the number token that follows each colon
long v = tokenAfterColon.Number;
if (!IsValidErrorCode(v)) throw new FormatException($"error code out of int range: {v}");

Prevention

When it happens

Trigger: Writing a per-node error code whose literal value exceeds the 32-bit signed integer range after a colon, e.g. `HP > 0:9999999999`, `Unit1.MP < 100:4294967296`, or a negative code below -2147483648. Reached from ParseUnary (line 81) and ParseCompare (line 113) when a Colon token is matched, then via ApplyErrorCode/ReadErrorCode.

Common situations: Author copies a full uint/hex error id from a design doc into the Luban/Excel condition cell without realizing the field is signed int32; pasting a 64-bit bit-packed flag value as an error code; negative hex literals that the lexer turns into out-of-range numbers.

Related errors


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