{"record":{"id":"59f9c6ce67b36878","repo":"Unity-Technologies/UnityCsReference","slug":"invalid-character-rightsymbol-in-expression","errorCode":null,"errorMessage":"Invalid character '{rightSymbol}' in expression","messagePattern":"Invalid character '(.+?)' in expression","errorType":"exception","errorClass":"ExpressionNotValidException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/Scripting/ScriptCompilation/VersionRanges.cs","lineNumber":119,"sourceCode":"            if (!versionTypeTraits.IsAllowedFirstCharacter(expression[0]))\n            {\n                leftSymbol = expression[0];\n                if (!Contains(k_LeftValidSymbols, leftSymbol))\n                {\n                    throw new ExpressionNotValidException($\"Invalid character '{leftSymbol}' in expression\", expression);\n                }\n\n                begin++;\n            }\n\n            var lastChar = expression[end];\n            if (!versionTypeTraits.IsAllowedLastCharacter(lastChar))\n            {\n                rightSymbol = lastChar;\n\n                if (!Contains(k_RightValidSymbols, rightSymbol))\n                {\n                    throw new ExpressionNotValidException($\"Invalid character '{rightSymbol}' in expression\", expression);\n                }\n\n                end--;\n            }\n\n            if ((leftSymbol != default(char) && rightSymbol == default(char)) ||\n                (leftSymbol == default(char) && rightSymbol != default(char)))\n            {\n                throw new ExpressionNotValidException(\"Incomplete expression, missing symbol in start or end\", expression);\n            }\n\n            int nextVersion;\n            string leftVersionString = PopVersionString(expression, begin, end, out nextVersion, versionTypeTraits);\n            var hasLeftVersion = !string.IsNullOrEmpty(leftVersionString);\n            if (hasLeftVersion)\n            {\n                expressionParsedData.leftVersion = (TVersion)m_versionTypeStaticFunctionalityProxy.Parse(leftVersionString);\n            }","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/Scripting/ScriptCompilation/VersionRanges.cs#L101-L137","documentation":"Thrown by ParseExpression (VersionRanges.cs:119) when the LAST character is neither an allowed version last-character (a digit or letter, per the version type traits) nor one of the legal right delimiters ']' or ')'. It is the lexical rejection of an unsupported closing token, mirroring error 721 for the trailing position.","triggerScenarios":"Expressions whose last character is '<', '>', '=', ',', whitespace, '.', '*', '+', '[', '(', etc. Concrete inputs: '[1.0,2.0,' (trailing comma, missing closer), '2.0<=' or '2.0>=', '1.0 ' (trailing space), '1.0.' (dangling dot), '1.0*' (trailing wildcard at end), '[1.0('.","commonSituations":"Typing a half-finished range and forgetting the closing delimiter ('[1.0,2.0,'); a trailing space from copy-paste; an operator suffix ('2.0>='); an incomplete version token ending in '.' ('1.0.').","solutions":["Close the range with the proper delimiter: '[1.0,2.0,' -> '[1.0,2.0]'.","Remove operator suffixes: '2.0>=' -> '(,2.0]'; '2.0<=' -> '(,2.0]'.","Trim trailing whitespace and stray punctuation: '1.0 ' -> '1.0', '1.0.' -> '1.0'.","Complete the version token so it does not end in '.' or '*'."],"exampleFix":"// before\n\"[1.0,2.0,\"   // or \"2.0<=\"  or \"1.0 \"\n// after\n\"[1.0,2.0]\"   // or \"(,2.0]\" or \"1.0\"","handlingStrategy":"validation","validationCode":"// Last char must be a digit, a letter, ']', or ')'.\nstatic bool HasValidClosing(string e) =>\n    !string.IsNullOrEmpty(e) &&\n    (char.IsDigit(e[e.Length-1]) ||\n     VersionTypeTraitsUtils.IsCharLetter(e[e.Length-1]) ||\n     e[e.Length-1] == ']' || e[e.Length-1] == ')');","typeGuard":"static bool ClosesWithLegalToken(string e) =>\n    !string.IsNullOrEmpty(e) &&\n    (char.IsDigit(e[e.Length-1]) ||\n     (e[e.Length-1] >= 'a' && e[e.Length-1] <= 'z') ||\n     (e[e.Length-1] >= 'A' && e[e.Length-1] <= 'Z') ||\n     e[e.Length-1] == ']' || e[e.Length-1] == ')');","tryCatchPattern":"try { var def = ranges.GetExpression(expr); }\ncatch (ExpressionNotValidException ex) when (ex.Message.Contains(\"Invalid character\")) {\n    ReportToUser($\"{expr}: bad closing character. End with a digit, letter, ']' or ')'.\");\n}","preventionTips":["Always close ranges with ']' or ')' before leaving the field.","Trim trailing whitespace and operator suffixes (> , =) from pasted text.","Avoid dangling '.' or '*' at the end of a version token."],"tags":["unity","asmdef","version-range","script-compilation","parsing"],"backgroundTag":null,"analyzedSha":"225b0fbdb57cc17d094e8056b71f8314aba56f73","analyzedAt":"2026-08-13T19:07:19.849Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}