dotnet/wpf · error · InvalidOperationException
SR.BamlScopeError
Error message
SR.BamlScopeError: {0} {1} What it means
BamlReader.ReadDocumentEndRecord pops the node stack expecting the matching DocumentStart record. If the popped node is anything else, the BAML stream's start/end records are unbalanced and the reader throws InvalidOperationException with SR.BamlScopeError, naming the unexpected record type and "DocumentEnd".
Solutions
- Regenerate the BAML by rebuilding the project — the stream is likely corrupt or hand-modified.
- Ensure every Read call sequence consumes all records (do not abandon reads mid-stream and reuse the reader).
- If generating BAML yourself, verify every DocumentStart/ElementStart record has its matching end record in order.
Defensive patterns
Strategy: try-catch
Validate before calling
// verify balanced document scope by walking records before reading
int depth = 0;
foreach (var r in records) {
if (r.RecordType == BamlRecordType.DocumentStart) depth++;
if (r.RecordType == BamlRecordType.DocumentEnd && --depth != 0)
throw new InvalidOperationException("Unbalanced DocumentStart/DocumentEnd in BAML.");
} Type guard
bool DocumentScopeBalanced(IEnumerable<BamlRecord> recs) => recs.Count(r => r.RecordType == BamlRecordType.DocumentStart) == recs.Count(r => r.RecordType == BamlRecordType.DocumentEnd);
Try / catch
try { reader.Read(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("DocumentEnd")) {
log.LogError("Unbalanced BAML document scope — regenerate the BAML resource.");
} Prevention
- Read BAML streams to completion; never abandon a reader mid-stream and reuse it.
- Rebuild after any manual resource manipulation.
- Hash-verify deployed assemblies to catch corrupted resources.
When it happens
Trigger: Calling ReadDocumentEndRecord (via Read when the stream yields a DocumentEnd record) while the top of _nodeStack is not BamlRecordType.DocumentStart — e.g. elements or properties were opened but never closed before the document end record.
Common situations: Corrupted or truncated BAML resource; a BAML stream assembled by custom tooling with mismatched start/end records; interrupting a read loop so records are skipped and the stack gets out of sync.
Understand the failure class
Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.
Related errors
- SR.BamlWriterBadScope
- Can't Assign to Known Type attributes
- Could not find prefix for type
- Found unexpected Xmlns BAML record
- NotImplementedException
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/9445131999b07193.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/BamlReader.cs:1851
}
/***************************************************************************\
*
* BamlReader.ReadDocumentEndRecord
*
* Read the end of the document record. This is used to flag that the end
* of the file has been reached.
*
\***************************************************************************/
private void ReadDocumentEndRecord()
{
// Pop information off the node stack to ensure we have matched all the
// start and end nodes and have nothing left but the start document node.
BamlNodeInfo nodeInfo = _nodeStack.Pop();
if (nodeInfo.RecordType != BamlRecordType.DocumentStart)
{
throw new InvalidOperationException(SR.Format(SR.BamlScopeError,
nodeInfo.RecordType.ToString(),
"DocumentEnd"));
}
ClearProperties();
NodeTypeInternal = BamlNodeType.EndDocument;
}
private void ReadAssemblyInfoRecord()
{
BamlAssemblyInfoRecord asmRecord = (BamlAssemblyInfoRecord)_currentBamlRecord;
MapTable.LoadAssemblyInfoRecord(asmRecord);
Assembly asm = Assembly.Load(asmRecord.AssemblyFullName);
foreach (XmlnsDefinitionAttribute xmlnsDef in asm.GetCustomAttributes(typeof(XmlnsDefinitionAttribute), true))
{
SetXmlNamespace(xmlnsDef.ClrNamespace, asm.FullName, xmlnsDef.XmlNamespace);
}View on GitHub (pinned to 81131a70a4)