dotnet/wpf · error · InvalidOperationException
SR.BamlWriterBadScope
Error message
SR.BamlWriterBadScope: {0} {1} What it means
WriteEndComplexProperty inspects the start-tag type of the currently open complex property and writes the matching end record. If the start tag is not a PropertyComplexStart (default case in its switch), it throws InvalidOperationException(SR.BamlWriterBadScope, startTagType, PropertyComplexEnd), indicating the end call does not match the open scope. This guards against mismatched push/pop of BAML records.
Solutions
- Call the matching End method: WriteEndArrayProperty, WriteEndIListProperty, or WriteEndIDictionaryProperty for their respective Start calls.
- Keep a stack of started scope types and pop with the exact matching End call.
- Fix ordering so element starts are closed with WriteEndElement, not WriteEndComplexProperty.
Example fix
// before
writer.WriteStartIListProperty("Children");
writer.WriteEndComplexProperty(); // mismatch
// after
writer.WriteStartIListProperty("Children");
writer.WriteEndIListProperty(); Defensive patterns
Strategy: validation
Validate before calling
var scopeStack = new Stack<BamlRecordType>();
void EndScope(BamlWriter w)
{
var start = scopeStack.Peek();
if (start == BamlRecordType.PropertyComplexStart) w.WriteEndComplexProperty();
else if (start == BamlRecordType.PropertyArrayStart) w.WriteEndArrayProperty();
else if (start == BamlRecordType.PropertyIListStart) w.WriteEndIListProperty();
else if (start == BamlRecordType.PropertyIDictionaryStart) w.WriteEndIDictionaryProperty();
scopeStack.Pop();
} Try / catch
try { writer.WriteEndComplexProperty(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("BamlWriterBadScope") || ex.Message.Contains("Property"))
{
// unwind scopes in a finally/stack-based manner instead
} Prevention
- Always pair Start/End calls via a scope stack.
- Never use WriteEndComplexProperty for array/IList/dictionary scopes.
- Close scopes in reverse order of opening.
When it happens
Trigger: Calling WriteEndComplexProperty when the open scope was actually started by an array start, IList start, IDictionary start, or element start — i.e. the wrong End method for the scope.
Common situations: Using WriteEndComplexProperty to close WriteStartArrayProperty/WriteStartIListProperty/WriteStartIDictionaryProperty scopes in a custom serializer; copy-pasted end calls in a state machine; exception unwinding that skipped the matching End call.
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
- SR.BamlWriterBadXmlns
- SR.BamlWriterNoInElement
- SR.BamlWriterStartDoc
- SR.BamlBadExtensionValue
- SR.BamlScopeError
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9033b919075c3600.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/BamlWriter.cs:794
XamlPropertyIDictionaryEndNode dictionaryEnd =
new XamlPropertyIDictionaryEndNode(
0,
0,
--_depth);
_bamlRecordWriter.WritePropertyIDictionaryEnd(dictionaryEnd);
break;
case BamlRecordType.PropertyComplexStart:
XamlPropertyComplexEndNode complexEnd =
new XamlPropertyComplexEndNode(
0,
0,
--_depth);
_bamlRecordWriter.WritePropertyComplexEnd(complexEnd);
break;
default:
throw new InvalidOperationException(
SR.Format(SR.BamlWriterBadScope,
startTagType.ToString(),
BamlRecordType.PropertyComplexEnd.ToString()));
}
_parserContext.PopScope();
}
/// <summary>
/// Write a literal content record to baml stream
/// </summary>
public void WriteLiteralContent(
string contents)
{
VerifyWriteState();
ProcessMarkupExtensionNodes();
XamlLiteralContentNode literalContent = new XamlLiteralContentNode(
0,View on GitHub (pinned to 81131a70a4)