OpenRA/OpenRA · error · InvalidDataException
Empty parenthesis at index {lastToken.Index}
Error message
Empty parenthesis at index {lastToken.Index} What it means
Thrown by VariableExpression.Build when an opening parenthesis is immediately followed by a closing parenthesis — i.e. '()' with no expression inside. Empty parenthetical grouping has no value. The message reports the index of the opening paren.
Source
Thrown at OpenRA.Game/Support/VariableExpression.cs:628
throw new InvalidDataException($"Unmatched closing parenthesis at index {token.Index}");
currentOpeners.Pop();
}
if (token.Opens != Grouping.None)
currentOpeners.Push(token);
if (lastToken == null)
{
// Expressions can't start with a binary or unary postfix operation or closer
if (token.LeftOperand)
throw new InvalidDataException($"Missing value or sub-expression at beginning for `{token.Symbol}` operator");
}
else
{
// Disallow empty parentheses
if (lastToken.Opens != Grouping.None && token.Closes != Grouping.None)
throw new InvalidDataException($"Empty parenthesis at index {lastToken.Index}");
// Exactly one of two consecutive tokens must take the other's sub-expression evaluation as an operand
if (lastToken.RightOperand == token.LeftOperand)
{
if (lastToken.RightOperand)
throw new InvalidDataException("Missing value or sub-expression or there is an extra operator " +
$"`{lastToken.Symbol}` at index {lastToken.Index} or `{token.Symbol}` at index {token.Index}");
throw new InvalidDataException($"Missing binary operation before `{token.Symbol}` at index {token.Index}");
}
}
if (token.Type == TokenType.Variable)
variables.Add(token.Symbol);
tokens.Add(token);
lastToken = token;
}
View on GitHub (pinned to a520984d91)
Solutions
- Remove the empty '()' pair, or fill it with a valid sub-expression.
- Check the index in the message and inspect the expression at that position.
- Ensure every parenthetical group contains at least one value or operation.
Example fix
# before — empty parentheses RequiresCondition: () && rank > 0 # after — remove or fill RequiresCondition: rank > 0
Defensive patterns
Strategy: validation
Validate before calling
// Reject empty parentheses.
using System.Text.RegularExpressions;
if (Regex.IsMatch(expression, @"\(\s*\)"))
throw new InvalidDataException("Empty parentheses are not valid in expressions."); Try / catch
try
{
var expr = new BooleanExpression(yamlValue);
}
catch (System.IO.InvalidDataException ex)
{
// Report: fill or remove the empty parentheses.
} Prevention
- Ensure every parenthesized group contains at least one value or operation.
- Remove placeholder '()' from template conditions.
- Run mod lint to catch empty groups.
When it happens
Trigger: An expression contains '()' as a sub-expression, e.g. '() + 1' or 'rank > ()'. The parser detects lastToken.Opens and token.Closes both set on consecutive tokens.
Common situations: A modder writes '()' as a placeholder or by mistake. A template leaves empty parentheses. Copy-paste drops the inner expression.
Related errors
- Unmatched closing parenthesis at index {token.Index}
- Number {Exts.ParseInt32Invariant(expression[start..i])} and
- Invalid identifier end character at index {i - 1} for `{expr
- Unexpected character '=' at index {start} - should it be `==
- Unexpected character '&' at index {start} - should it be `&&
AI-assisted analysis of OpenRA/OpenRA@a520984d91 (2026-08-13).
Data as JSON: /api/errors/e0f527d7890da7c6.
Report an issue: GitHub.