babalae/better-genshin-impact · error · InvalidOperationException

函数 {name} 缺少右括号

Error message

函数 {name} 缺少右括号

What it means

Thrown by ConditionEvaluator.ParsePrimary when parsing a function call (identifier followed by '(') and the arguments are consumed but no ')' follows. This is the function-call-specific variant of the missing-parenthesis error. When called via Evaluate(), this is caught internally and Evaluate returns false.

Source

Thrown at BetterGenshinImpact/GameTask/AutoFight/Script/ConditionEvaluator.cs:362

        }

        if (tokens[pos].Type == TokenType.Identifier)
        {
            var name = tokens[pos].Value; pos++;
            if (tokens[pos].Type == TokenType.LParen)
            {
                pos++;
                var args = new List<AstNode>();
                if (tokens[pos].Type != TokenType.RParen)
                {
                    args.Add(ParseOrExpr(tokens, ref pos));
                    while (tokens[pos].Type == TokenType.Comma)
                    {
                        pos++;
                        args.Add(ParseOrExpr(tokens, ref pos));
                    }
                }
                if (tokens[pos].Type != TokenType.RParen) throw new InvalidOperationException($"函数 {name} 缺少右括号");
                pos++;
                return new FuncCallNode(name, args);
            }
            return new FuncCallNode(name, []);
        }

        if (tokens[pos].Type == TokenType.Number)
        {
            var val = double.Parse(tokens[pos].Value, CultureInfo.InvariantCulture); pos++;
            return new NumberNode(val);
        }

        if (tokens[pos].Type == TokenType.Bool)
        {
            var val = tokens[pos].Value == "true"; pos++;
            return new BoolNode(val);
        }

View on GitHub (pinned to a7cb36712d)

Solutions

  1. Check the function name in the error message ({name}) to locate the problematic call.
  2. Ensure every function call has a closing ')' after its last argument.
  3. Review multi-argument function syntax: func(arg1, arg2, ...) must end with ')'.
  4. Validate expressions before use with a test Evaluate call.

Example fix

// before (missing closing paren on function)
"condition": "since(1 > 5"

// after
"condition": "since(1) > 5"
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify all function calls in the expression are properly closed
static bool AreFunctionCallsClosed(string expr)
{
    int depth = 0;
    bool inFunc = false;
    for (int i = 0; i < expr.Length; i++)
    {
        if (expr[i] == '(') { depth++; inFunc = true; }
        if (expr[i] == ')') { depth--; inFunc = false; }
        if (depth < 0) return false;
    }
    return depth == 0 && !inFunc;
}

Try / catch

// Evaluate catches this internally and returns false.
// The warning log at line 149 includes the expression and error message,
// so check application logs for '条件表达式求值失败' to find the problematic expression.

Prevention

When it happens

Trigger: A condition expression with a function call missing its closing ')', e.g. `since(1, true, 香菱` or `count(3, 0`. After parsing all comma-separated arguments, the parser expects ')' but finds End or another token.

Common situations: User writes a JSON strategy condition with a function call that is missing its closing ')'. Common when functions have multiple arguments and the user forgets the final paren, e.g. `last-exec(5, true`.

Related errors


AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13). Data as JSON: /api/errors/79845c15cdc4871c. Report an issue: GitHub.