dotnet/wpf · error

SR.Format(SR.BamlWriterBadScope, startTagState.ToString()…

Error message

SR.Format(SR.BamlWriterBadScope, startTagState.ToString(), endTagBeingWritten.ToString())

What it means

BamlWriter tracks a scope stack of opened BAML records (elements, properties, constructors). VerifyEndTagState pops the stack and, when the record on top does not match the tag kind currently being closed, throws InvalidOperationException('Bad scope'). It signals a mismatch between the write calls made and the structure of the BAML document being produced.

Solutions

  1. Ensure every WriteStartElement/WriteEndElement/WriteStartConstructor/WriteEndConstructor call is properly paired and nested
  2. Check that WriteEndDocument is only called after all open scopes are closed
  3. If wrapping BamlWriter, mirror all calls one-to-one to the underlying writer
  4. Debug the scope mismatch by logging each Push/Pop (start/end) call sequence before the throw

Example fix

// before
writer.WriteStartElement(elementType);
writer.WriteStartConstructor();
writer.WriteEndElement(); // bad scope: constructor still open
// after
writer.WriteStartElement(elementType);
writer.WriteStartConstructor();
writer.WriteEndConstructor();
writer.WriteEndElement();
Defensive patterns

Strategy: try-catch

Validate before calling

if (openScopes.Count == 0 || openScopes.Peek() != expectedStartTag) throw new InvalidOperationException("Unbalanced BamlWriter scope: cannot close " + endTagBeingWritten);

Type guard

bool CanClose(BamlWriter w, BamlRecordType expected) => openScopes.Count > 0 && openScopes.Peek() == expected;

Try / catch

try { writer.WriteEndElement(); } catch (InvalidOperationException ex) when (ex.Message.Contains("scope")) { LogUnbalancedScope(ex); throw; }

Prevention

When it happens

Trigger: Calling BamlWriter.WriteEndElement, WriteEndConstructor, or WriteEndDocument when the innermost open record is of a different kind (e.g. WriteEndElement while a constructor or property record is on the stack, or closing elements out of order).

Common situations: Custom markup writers or serializers hand-building BAML streams; buggy code that interleaves WriteStartElement/WriteEndElement pairs incorrectly; calling WriteEndDocument while elements are still open or vice versa.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/BamlWriter.cs:1043

    *
    * BamlWriter.VerifyEndTagState
    *
    * Verify that we are in a good state to perform a record write and that
    * the xamlnodetype on the node type stack is of the expected type.  This
    * is called when an end tag record is written
    *
    \***************************************************************************/
    
    private void VerifyEndTagState(
        BamlRecordType   expectedStartTag,
        BamlRecordType   endTagBeingWritten)
    {
        VerifyWriteState();

        BamlRecordType startTagState = Pop();
        if (startTagState != expectedStartTag)
        {
            throw new InvalidOperationException(SR.Format(SR.BamlWriterBadScope,
                                                       startTagState.ToString(),
                                                       endTagBeingWritten.ToString()));
        }
    }

    /***************************************************************************\
    *
    * BamlWriter.GetAssembly
    *
    * Get the Assembly given a name.  This uses the LoadWrapper to load the
    * assembly from the current directory.  
    * NOTE:  Assembly paths are not currently supported, but may be in the
    *        future if the need arises.
    *
    \***************************************************************************/

    private Assembly GetAssembly(string assemblyName)
    {

View on GitHub (pinned to 81131a70a4)