{"record":{"id":"e3e24cf3c3d61373","repo":"dotnet/wpf","slug":"sr-format-sr-tokenizerhelpermissingendquote-str","errorCode":null,"errorMessage":"SR.Format(SR.TokenizerHelperMissingEndQuote, _str)","messagePattern":"SR\\.Format\\(SR\\.TokenizerHelperMissingEndQuote, _str\\)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/TokenizerHelper.cs","lineNumber":229,"sourceCode":"                }\n                else if ((Char.IsWhiteSpace(currentChar)) || (currentChar == separator))\n                {\n                    if (currentChar == separator)\n                    {\n                        _foundSeparator = true;\n                    }\n                    break;\n                }\n\n                ++_charIndex;\n                ++newTokenLength;\n            }\n\n            // if quoteCount isn't zero we hit the end of the string\n            // before the ending quote\n            if (quoteCount > 0)\n            {\n                throw new System.InvalidOperationException(SR.Format(SR.TokenizerHelperMissingEndQuote, _str));                \n            }\n\n            ScanToNextToken(separator); // move so at the start of the nextToken for next call\n\n            // finally made it, update the _currentToken values\n            _currentTokenIndex = newTokenIndex;\n            _currentTokenLength = newTokenLength;\n\n            if (_currentTokenLength < 1)\n            {\n                throw new System.InvalidOperationException(SR.Format(SR.TokenizerHelperEmptyToken, _charIndex, _str));\n            }\n\n            return true;\n        }\n\n        // helper to move the _charIndex to the next token or to the end of the string\n        private void ScanToNextToken(char separator)","sourceCodeStart":211,"sourceCodeEnd":247,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/TokenizerHelper.cs#L211-L247","documentation":"TokenizerHelper.NextToken throws InvalidOperationException with TokenizerHelperMissingEndQuote when it reaches end of string while inside a quoted token (quoteCount > 0). The library requires quoted tokens to be closed before the string ends.","triggerScenarios":"Calling NextToken(true) (allowQuotedToken) with a string containing an opening quote character that is never closed, e.g. '\"abc' or \"'12,34\".","commonSituations":"XAML MiniLanguage values where a quoted fragment lost its closing quote during manual editing or string concatenation; escaping mistakes when building token strings in code.","solutions":["Add the matching closing quote to the token string","Check quote balance in the input before parsing","Avoid embedding quote characters unless quoted tokens are intended","Catch InvalidOperationException and show which string failed to tokenize"],"exampleFix":"// before\nvar th = new TokenizerHelper(\"'abc def\", ',', culture);\nth.NextToken(true);\n// after\nvar th = new TokenizerHelper(\"'abc def'\", ',', culture);\nth.NextToken(true);","handlingStrategy":"validation","validationCode":"static bool QuotesBalanced(string s) =>\n    s.Count(c => c == '\"') % 2 == 0 && s.Count(c => c == '\\'') % 2 == 0;","typeGuard":null,"tryCatchPattern":"try { ok = helper.NextToken(true); }\ncatch (InvalidOperationException) { /* unterminated quote: repair or reject input */ }","preventionTips":["Always close quoted tokens in generated strings","Escape/strip quote characters not intended as delimiters","Unit-test parsers with quote-edge-case inputs"],"tags":["wpf","tokenizer","unterminated-quote","parse-error"],"backgroundTag":"invalid-argument-format","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-21T21:30:21.729Z"}