babalae/better-genshin-impact · error · InvalidOperationException
缺少右括号
Error message
缺少右括号
What it means
Thrown by ConditionEvaluator.ParsePrimary when a parenthesized sub-expression (opened with '(') is parsed but the closing ')' is not found at the expected position. This is a syntax error in the condition expression: an unbalanced '('. When called via Evaluate(), this is caught internally and Evaluate returns false.
Source
Thrown at BetterGenshinImpact/GameTask/AutoFight/Script/ConditionEvaluator.cs:341
{
var op = tokens[pos].Value; pos++;
return new UnaryOpNode(op, ParseUnaryExpr(tokens, ref pos));
}
if (tokens[pos].Type == TokenType.Minus)
{
pos++;
return new UnaryOpNode("-u", ParseUnaryExpr(tokens, ref pos));
}
return ParsePrimary(tokens, ref pos);
}
private static AstNode ParsePrimary(List<Token> tokens, ref int pos)
{
if (tokens[pos].Type == TokenType.LParen)
{
pos++;
var node = ParseOrExpr(tokens, ref pos);
if (tokens[pos].Type != TokenType.RParen) throw new InvalidOperationException("缺少右括号");
pos++;
return node;
}
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));View on GitHub (pinned to a7cb36712d)
Solutions
- Count and balance all '(' and ')' in the condition expression.
- The expression engine does not support implicit grouping — every '(' must have a matching ')'.
- Simplify complex nested expressions and rebuild them incrementally, testing each part.
- Use the Evaluate method in a dry-run with logging to identify the exact failure point.
Example fix
// before (unclosed paren) "condition": "(q-ready() && low-hp" // after "condition": "(q-ready() && low-hp())"
Defensive patterns
Strategy: try-catch
Validate before calling
// Quick balance check for parentheses in a condition expression
static bool AreParensBalanced(string expr)
{
int depth = 0;
foreach (var c in expr)
{
if (c == '(') depth++;
if (c == ')') depth--;
if (depth < 0) return false;
}
return depth == 0;
}
if (!AreParensBalanced(conditionExpr))
Log.LogWarning("条件表达式括号不平衡: {Expr}", conditionExpr); Try / catch
// Evaluate catches this internally (line 147-151) and returns false.
// No additional try-catch needed when using Evaluate.
// For safety, log the expression when Evaluate returns unexpected false:
var result = evaluator.Evaluate(expr, index, charName, actionName);
if (!result && /* expected true context */)
Logger.LogWarning("条件求值返回false,可能表达式有语法错误: {Expr}", expr); Prevention
- The Evaluate method already handles this — it returns false rather than throwing.
- When debugging conditions that always evaluate false, check for unbalanced parentheses.
- Use a parenthesis counter when writing complex nested conditions.
- Log the expression string alongside the Evaluate result to correlate failures.
When it happens
Trigger: A condition expression with an unclosed parenthesis, e.g. `(q-ready() && low-hp` or `since(1 > 5`. The parser enters ParsePrimary expecting ')' after the inner expression, but finds a different token (End, or another operator/identifier).
Common situations: User writes a JSON strategy condition with a missing ')', or has unbalanced parentheses from manual editing. For example: `"condition": "(q-ready() && low-hp"` — the outer '(' is never closed.
Related errors
AI-assisted analysis of babalae/better-genshin-impact@a7cb36712d (2026-08-13).
Data as JSON: /api/errors/02964799fb52470b.
Report an issue: GitHub.