dotnet/wpf · error · InvalidOperationException

SR.Format(SR.TokenizerHelperMissingEndQuote, _str)

Error message

SR.Format(SR.TokenizerHelperMissingEndQuote, _str)

What it means

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.

Solutions

  1. Add the matching closing quote to the token string
  2. Check quote balance in the input before parsing
  3. Avoid embedding quote characters unless quoted tokens are intended
  4. Catch InvalidOperationException and show which string failed to tokenize

Example fix

// before
var th = new TokenizerHelper("'abc def", ',', culture);
th.NextToken(true);
// after
var th = new TokenizerHelper("'abc def'", ',', culture);
th.NextToken(true);
Defensive patterns

Strategy: validation

Validate before calling

static bool QuotesBalanced(string s) =>
    s.Count(c => c == '"') % 2 == 0 && s.Count(c => c == '\'') % 2 == 0;

Try / catch

try { ok = helper.NextToken(true); }
catch (InvalidOperationException) { /* unterminated quote: repair or reject input */ }

Prevention

When it happens

Trigger: Calling NextToken(true) (allowQuotedToken) with a string containing an opening quote character that is never closed, e.g. '"abc' or "'12,34".

Common situations: 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.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/e3e24cf3c3d61373. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/TokenizerHelper.cs:229

                }
                else if ((Char.IsWhiteSpace(currentChar)) || (currentChar == separator))
                {
                    if (currentChar == separator)
                    {
                        _foundSeparator = true;
                    }
                    break;
                }

                ++_charIndex;
                ++newTokenLength;
            }

            // if quoteCount isn't zero we hit the end of the string
            // before the ending quote
            if (quoteCount > 0)
            {
                throw new System.InvalidOperationException(SR.Format(SR.TokenizerHelperMissingEndQuote, _str));                
            }

            ScanToNextToken(separator); // move so at the start of the nextToken for next call

            // finally made it, update the _currentToken values
            _currentTokenIndex = newTokenIndex;
            _currentTokenLength = newTokenLength;

            if (_currentTokenLength < 1)
            {
                throw new System.InvalidOperationException(SR.Format(SR.TokenizerHelperEmptyToken, _charIndex, _str));
            }

            return true;
        }

        // helper to move the _charIndex to the next token or to the end of the string
        private void ScanToNextToken(char separator)

View on GitHub (pinned to 81131a70a4)