Unity-Technologies/UnityCsReference · error · ExpressionNotValidException

Incomplete expression, missing symbol in start or end

Error message

Incomplete expression, missing symbol in start or end

What it means

Thrown by ParseExpression (VersionRanges.cs:128) when exactly ONE of the two delimiters is present: a left delimiter ('[' or '(') was consumed but no right delimiter (']' or ')'), or vice versa. It catches unbalanced bracket expressions that survive the individual first/last-character checks.

Source

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

            }

            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--;
            }

            if ((leftSymbol != default(char) && rightSymbol == default(char)) ||
                (leftSymbol == default(char) && rightSymbol != default(char)))
            {
                throw new ExpressionNotValidException("Incomplete expression, missing symbol in start or end", expression);
            }

            int nextVersion;
            string leftVersionString = PopVersionString(expression, begin, end, out nextVersion, versionTypeTraits);
            var hasLeftVersion = !string.IsNullOrEmpty(leftVersionString);
            if (hasLeftVersion)
            {
                expressionParsedData.leftVersion = (TVersion)m_versionTypeStaticFunctionalityProxy.Parse(leftVersionString);
            }

            int notNeeded;
            string rightVersionString = PopVersionString(expression, nextVersion, end, out notNeeded, versionTypeTraits);
            var hasRightVersion = !string.IsNullOrEmpty(rightVersionString);
            if (hasRightVersion)
            {
                expressionParsedData.rightVersion = (TVersion)m_versionTypeStaticFunctionalityProxy.Parse(rightVersionString);
            }
            expressionParsedData.GenerateExpressionTypeKey = new ExpressionTypeKey(leftSymbol: leftSymbol, rightSymbol: rightSymbol, hasSeparator: hasSeperator, hasLeftVersion: hasLeftVersion, hasRightVersion: hasRightVersion);

View on GitHub (pinned to 225b0fbdb5)

Solutions

  1. Add the missing delimiter: '[1.0' -> '[1.0]'; '1.0]' -> '[1.0]'.
  2. If a single bare version was intended, remove the stray bracket entirely: '[1.0' -> '1.0'.
  3. Balance both ends for a range: '[1.0,2.0' -> '[1.0,2.0]'.

Example fix

// before
"[1.0"        // or "1.0]"  or "[1.0,2.0"
// after
"[1.0]"       // or "1.0"   or "[1.0,2.0]"
Defensive patterns

Strategy: validation

Validate before calling

// A range expression must have balanced delimiters (0 or 1 of each side).
static bool DelimitersBalanced(string e) {
    if (string.IsNullOrEmpty(e)) return false;
    int open  = 0, close = 0;
    foreach (var c in e) {
        if (c == '[' || c == '(') open++;
        else if (c == ']' || c == ')') close++;
    }
    return open == close && open <= 1;
}
// Combine with the full k_ValidRange guard for a strict pre-check.

Type guard

static bool HasBalancedDelimiters(string e) {
    if (string.IsNullOrEmpty(e)) return false;
    int open = 0, close = 0;
    foreach (var c in e) {
        if (c == '[' || c == '(') open++;
        else if (c == ']' || c == ')') close++;
    }
    return open == close;
}

Try / catch

try { var def = ranges.GetExpression(expr); }
catch (ExpressionNotValidException ex) when (ex.Message.Contains("Incomplete expression")) {
    ReportToUser($"{expr}: unbalanced '[' / ']' or '(' / ')'. Add the missing delimiter or remove the stray one.");
}

Prevention

When it happens

Trigger: Inputs with a single delimiter: '[1.0' (opener, no closer), '1.0]' (closer, no opener), '[1.0,2.0' (missing right bracket), '(1.0'. For the imbalance to be detected here (rather than 721/722), the opposite end must land on a valid version character so its symbol defaults to '\0'.

Common situations: Typing a half-finished range in the inspector and tabbing away; deleting a closing bracket during editing; copy-paste truncation that drops the trailing delimiter.

Related errors


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