dotnet/wpf · error · XamlUnexpectedParseException

EmptyElement ::= . EMPTYELEMENT DIRECTIVE* ATTRIBUTE*.

Error message

EmptyElement ::= . EMPTYELEMENT DIRECTIVE* ATTRIBUTE*.

What it means

XamlPullParser.P_EmptyElement implements `EmptyElement ::= EMPTYELEMENT DIRECTIVE* ATTRIBUTE*`. It throws XamlUnexpectedParseException when the scanner's current NodeType is not EMPTYELEMENT, since this method may only run when a self-closing element token (<Tag/>) is current. The check enforces the parser's grammar contract that P_Element dispatches to P_EmptyElement only for empty-element tokens.

Solutions

  1. If using a custom scanner, ensure it sets NodeType to EMPTYELEMENT exactly for self-closing tags.
  2. Do not call P_EmptyElement directly; always go through P_Element which validates the node type.
  3. Validate the XAML is well-formed XML before parsing.
  4. Update to a patched System.Xaml/WPF version if a scanner-state bug is suspected.

Example fix

// before: direct call with wrong node state
parser.P_EmptyElement();

// after: go through the validating dispatcher
parser.P_Element();
Defensive patterns

Strategy: try-catch

Try / catch

try { return XamlReader.Parse(xaml); } catch (XamlUnexpectedParseException ex) { Log($"Grammar violation at {ex.LineNumber}:{ex.LinePosition}"); return null; }

Prevention

When it happens

Trigger: P_Element dispatching to the empty-element branch while the scanner holds another node type — possible with a custom/injected scanner or reordered node stream; in normal use only from corrupted scanner state or non-well-formed input.

Common situations: Custom XamlReader/scanner implementations violating the ScannerNodeType contract; testing harnesses calling P_EmptyElement directly with the wrong current node; parser bugs after scanner state corruption.

Understand the failure class

Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/Parser/XamlPullParser.cs:125

                foreach (XamlNode node in P_ElementBody())
                {
                    yield return node;
                }

                break;
            default:
                throw new XamlUnexpectedParseException(_xamlScanner, nodeType, ElementRuleException);
            }
        }

        ///////////////////////////
        //  EmptyElement ::= EMPTYELEMENT DIRECTIVE* ATTRIBUTE*
        //
        public IEnumerable<XamlNode> P_EmptyElement()
        {
            if (_xamlScanner.NodeType != ScannerNodeType.EMPTYELEMENT)
            {
                throw new XamlUnexpectedParseException(_xamlScanner, _xamlScanner.NodeType,
                    EmptyElementRuleException);
            }

            yield return Logic_StartObject(_xamlScanner.Type, _xamlScanner.Namespace);
            _xamlScanner.Read();
            if (ProvideLineInfo)
            {
                yield return Logic_LineInfo();
            }

            while (_xamlScanner.NodeType == ScannerNodeType.DIRECTIVE)
            {
                // Directives are processed exactly like Attributes.
                foreach (XamlNode node in LogicStream_Attribute())
                {
                    yield return node;
                }

View on GitHub (pinned to 81131a70a4)