{"record":{"id":"d3e185dc3f86f11f","repo":"Unity-Technologies/UnityCsReference","slug":"incomplete-expression-missing-symbol-in-start-or","errorCode":null,"errorMessage":"Incomplete expression, missing symbol in start or end","messagePattern":"Incomplete expression, missing symbol in start or end","errorType":"exception","errorClass":"ExpressionNotValidException","httpStatus":null,"severity":"error","filePath":"Editor/Mono/Scripting/ScriptCompilation/VersionRanges.cs","lineNumber":128,"sourceCode":"            }\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            }\n\n            int notNeeded;\n            string rightVersionString = PopVersionString(expression, nextVersion, end, out notNeeded, versionTypeTraits);\n            var hasRightVersion = !string.IsNullOrEmpty(rightVersionString);\n            if (hasRightVersion)\n            {\n                expressionParsedData.rightVersion = (TVersion)m_versionTypeStaticFunctionalityProxy.Parse(rightVersionString);\n            }\n            expressionParsedData.GenerateExpressionTypeKey = new ExpressionTypeKey(leftSymbol: leftSymbol, rightSymbol: rightSymbol, hasSeparator: hasSeperator, hasLeftVersion: hasLeftVersion, hasRightVersion: hasRightVersion);","sourceCodeStart":110,"sourceCodeEnd":146,"githubUrl":"https://github.com/Unity-Technologies/UnityCsReference/blob/225b0fbdb57cc17d094e8056b71f8314aba56f73/Editor/Mono/Scripting/ScriptCompilation/VersionRanges.cs#L110-L146","documentation":"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.","triggerScenarios":"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'.","commonSituations":"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.","solutions":["Add the missing delimiter: '[1.0' -> '[1.0]'; '1.0]' -> '[1.0]'.","If a single bare version was intended, remove the stray bracket entirely: '[1.0' -> '1.0'.","Balance both ends for a range: '[1.0,2.0' -> '[1.0,2.0]'."],"exampleFix":"// before\n\"[1.0\"        // or \"1.0]\"  or \"[1.0,2.0\"\n// after\n\"[1.0]\"       // or \"1.0\"   or \"[1.0,2.0]\"","handlingStrategy":"validation","validationCode":"// A range expression must have balanced delimiters (0 or 1 of each side).\nstatic bool DelimitersBalanced(string e) {\n    if (string.IsNullOrEmpty(e)) return false;\n    int open  = 0, close = 0;\n    foreach (var c in e) {\n        if (c == '[' || c == '(') open++;\n        else if (c == ']' || c == ')') close++;\n    }\n    return open == close && open <= 1;\n}\n// Combine with the full k_ValidRange guard for a strict pre-check.","typeGuard":"static bool HasBalancedDelimiters(string e) {\n    if (string.IsNullOrEmpty(e)) return false;\n    int open = 0, close = 0;\n    foreach (var c in e) {\n        if (c == '[' || c == '(') open++;\n        else if (c == ']' || c == ')') close++;\n    }\n    return open == close;\n}","tryCatchPattern":"try { var def = ranges.GetExpression(expr); }\ncatch (ExpressionNotValidException ex) when (ex.Message.Contains(\"Incomplete expression\")) {\n    ReportToUser($\"{expr}: unbalanced '[' / ']' or '(' / ')'. Add the missing delimiter or remove the stray one.\");\n}","preventionTips":["Treat a lone '[' or '(' as an incomplete edit; close it or drop it.","When a single bare version is intended, use no delimiters at all ('1.0').","Validate balance before saving the .asmdef."],"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"}