Unity-Technologies/UnityCsReference · error · ExpressionNotValidException

Invalid character '{leftSymbol}' in expression

Error message

Invalid character '{leftSymbol}' in expression

What it means

Thrown by ParseExpression (VersionRanges.cs:106) when the FIRST character of the expression is neither an allowed version first-character (a digit, per both UnityVersionTypeTraits and SemVersionTypeTraits) nor one of the legal left delimiters '[' or '('. It is a lexical rejection of an unsupported opening token, raised before any structural analysis.

Source

Thrown at Editor/Mono/Scripting/ScriptCompilation/VersionRanges.cs:106

            {
                return expressionParsedData;
            }

            IVersionTypeTraits versionTypeTraits = m_versionTypeStaticFunctionalityProxy.GetVersionTypeTraits();

            bool hasSeperator = Contains(expression, ',');
            char leftSymbol = default(char);
            char rightSymbol = default(char);

            int begin = 0;
            int end = expression.Length - 1;

            if (!versionTypeTraits.IsAllowedFirstCharacter(expression[0]))
            {
                leftSymbol = expression[0];
                if (!Contains(k_LeftValidSymbols, leftSymbol))
                {
                    throw new ExpressionNotValidException($"Invalid character '{leftSymbol}' in expression", expression);
                }

                begin++;
            }

            var lastChar = expression[end];
            if (!versionTypeTraits.IsAllowedLastCharacter(lastChar))
            {
                rightSymbol = lastChar;

                if (!Contains(k_RightValidSymbols, rightSymbol))
                {
                    throw new ExpressionNotValidException($"Invalid character '{rightSymbol}' in expression", expression);
                }

                end--;
            }

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Replace operator prefixes with the delimiter grammar: '>=1.0' -> '1.0'; '>1.0' -> '(1.0,)'; '<=2.0' -> '(,2.0]'; '<2.0' -> '(,2.0)'.
  2. Remove any leading whitespace or version prefix: 'v1.0' -> '1.0', ' 1.0' -> '1.0'.
  3. Replace npm caret/tilde: '^1.0' or '~1.0' -> '1.0' (or '[1.0,2.0)' if you want the caret upper bound).
  4. Ensure the expression opens with a digit or with '[' / '('; no other opener is legal.

Example fix

// before
">=1.0"   // or "^1.0.0"  or " 1.0"
// after
"1.0"     // means x >= 1.0
Defensive patterns

Strategy: validation

Validate before calling

// First char must be a digit, '[', or '('.
static bool HasValidOpening(string e) =>
    !string.IsNullOrEmpty(e) &&
    (char.IsDigit(e[0]) || e[0] == '[' || e[0] == '(');

// Full-shape guard also rejects bad openers:
static bool IsValidVersionRangeExpression(string e) =>
    !string.IsNullOrEmpty(e) && k_ValidRange.IsMatch(e);

Type guard

static bool OpensWithLegalToken(string e) =>
    !string.IsNullOrEmpty(e) &&
    (char.IsDigit(e[0]) || e[0] == '[' || e[0] == '(');

Try / catch

try { var def = ranges.GetExpression(expr); }
catch (ExpressionNotValidException ex) when (ex.Message.Contains("Invalid character")) {
    ReportToUser($"{expr}: bad opening character. Use a digit or '[' / '('.");
}

Prevention

When it happens

Trigger: Expressions whose first character is ']', ')', '<', '>', '=', whitespace, any letter (a-z), ',', '*', '+', '~', '^', etc. Concrete inputs: '>=1.0', '>1.0', '<2.0', '<=2.0', ']1.0]', ' 1.0' (leading space), 'v1.0', 'x1.0', '*1.0', '~1.0', '^1.0' (npm-style).

Common situations: Porting npm ('^1.0', '~1.0'), Maven, or comparison-operator ('>=1.0', '>1.0') range syntax into a Unity Version Define; pasting an expression with a leading space that the Define-Constraints trimmer does not strip (DefineConstraintsHelper trims '||'-split define tokens, not interior/leading chars of a version-range expression); using a version prefix like 'v'.

Understand the failure class

Related errors


AI-assisted analysis of Unity-Technologies/UnityCsReference@225b0fbdb5 (2026-08-13). Data as JSON: /api/errors/6868f9cd63baa6a1. Report an issue: GitHub.