dotnet/wpf · error · InvalidOperationException

throw new InvalidOperationException();

Error message

throw new InvalidOperationException();

What it means

AddBracketCharacters throws a bare InvalidOperationException when a caller registers a bracket pair whose characters fail the bracket constraints. The class tokenizes custom opening/closing bracket characters for XAML-style markup extension parsing, and it refuses to append a pair that is not a valid bracket character. The message is empty, so the real cause must be inferred from the character values passed in.

Solutions

  1. Inspect the openingBracket and closingBracket arguments; ensure they are different, non-alphanumeric, non-whitespace characters
  2. Exclude restricted characters: = , ' " { } \ — pick another symbol pair such as [ ] or < >
  3. Verify initialization order: brackets can only be added while _initializing is true; adding after tokenization started invalidates state
  4. Wrap the AddBracketCharacters call in a try-catch and log the character codes for diagnostics

Example fix

// before
parser.AddBracketCharacters('(', '(');
// after
parser.AddBracketCharacters('(', ')');
Defensive patterns

Strategy: validation

Validate before calling

bool IsValidPair(char open, char close) =>
    open != close &&
    !char.IsLetterOrDigit(open) && !char.IsLetterOrDigit(close) &&
    !char.IsWhiteSpace(open) && !char.IsWhiteSpace(close) &&
    !"=,'\"{}\\".Contains(open) && !"=,'\"{}\\".Contains(close);

Try / catch

try { parser.AddBracketCharacters(open, close); }
catch (InvalidOperationException ex) { log.Warn($"Invalid bracket pair {(int)open}/{(int)close}: {ex.Message}"); }

Prevention

When it happens

Trigger: Calling AddBracketCharacters(openingBracket, closingBracket) with a pair that violates the rules enforced by IsValidBracketCharacter: identical open/close characters, alphanumeric or whitespace characters, or a character in the restricted set (= , ' " { } \). Note Tokenize/initialization paths route through the same validation.

Common situations: Custom markup extension configuration in WPF XAML parsing where an escape/bracket override uses e.g. '[' and ']' is fine, but a developer passes '(' and '(' (same char), or uses a letter like 'q' as a delimiter, or reuses '{' as an opening bracket while it is already reserved.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/Shared/MS/Internal/Xaml/Parser/SpecialBracketCharacters.cs:51

        internal SpecialBracketCharacters(IReadOnlyDictionary<char, char> attributeList)
        {
            BeginInit();
            if (attributeList is not null && attributeList.Count > 0)
            {
                Tokenize(attributeList);
            }
        }

        internal void AddBracketCharacters(char openingBracket, char closingBracket)
        {
            if (_initializing)
            {
                _startCharactersStringBuilder.Append(openingBracket);
                _endCharactersStringBuilder.Append(closingBracket);
            }
            else
            {
                throw new InvalidOperationException();
            }
        }

        private void Tokenize(IReadOnlyDictionary<char, char> attributeList)
        {
            if (_initializing)
            {
                foreach (char openingBracket in attributeList.Keys)
                {
                    char closingBracket = attributeList[openingBracket];
                    string errorMessage = string.Empty;
                    if (IsValidBracketCharacter(openingBracket, closingBracket))
                    {
                        _startCharactersStringBuilder.Append(openingBracket);
                        _endCharactersStringBuilder.Append(closingBracket);
                    }
                }
            }

View on GitHub (pinned to 81131a70a4)