dotnet/wpf · error · InvalidOperationException
InvalidOperationException(SR.Format(SR.XamlXmlWriterWriteNot…
Error message
InvalidOperationException(SR.Format(SR.XamlXmlWriterWriteNotSupportedInCurrentState, "WriteEndObject"))
What it means
On WriteEndObject the writer pops the current namespace-scope frame and validates that the frame was created by a StartObject or GetObject node. If the frame's AllocatingNodeType is something else (e.g. created for a member or value), the object being ended does not correspond to an object start, so it throws InvalidOperationException 'WriteEndObject not supported in current state'. This protects the element nesting of the emitted XML.
Solutions
- Ensure every WriteEndObject matches a prior WriteStartObject or WriteGetObject at the same frame level
- End any open members (WriteEndMember) before WriteEndObject
- Log/balance node emissions in the writing loop to detect mismatches early
Example fix
// before writer.WriteStartMember(m); writer.WriteEndObject(); // wrong frame -> throws // after writer.WriteStartMember(m); writer.WriteEndMember(); writer.WriteEndObject();
Defensive patterns
Strategy: validation
Validate before calling
if (openFrameAllocatedBy != "StartObject" && openFrameAllocatedBy != "GetObject") throw new InvalidOperationException("WriteEndObject requires an object frame"); Type guard
bool CanWriteEndObject(XamlNodeType frameAllocType) => frameAllocType is XamlNodeType.StartObject or XamlNodeType.GetObject;
Try / catch
try { writer.WriteEndObject(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("WriteEndObject")) { /* rebalance frames: close member or abort */ } Prevention
- Maintain an explicit frame stack in your emission loop
- Always end members before ending objects
- Count starts vs ends and assert balance at stream end
When it happens
Trigger: Calling XamlXmlWriter.WriteEndObject when the innermost frame was allocated by WriteStartMember/WriteValue rather than WriteStartObject/WriteGetObject — i.e. mismatched start/end pairs.
Common situations: Hand-rolled node loops where an EndObject is emitted after a member without closing the member first; error-recovery code that skips starts but still emits ends; duplicated WriteEndObject calls.
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.TemplateContentSetTwice
- SR.XamlXmlWriterWriteNotSupportedInCurrentState (WriteValue)
- SR.XamlXmlWriterWriteObjectNotSupportedInCurrentState
- XamlXmlWriterException(SR.Format(SR.XamlXmlWriterWriteNotSup…
- XamlXmlWriterException(SR.Format(SR.XamlXmlWriterWriteNotSup…
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/f1afe9c7c8ae42be.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlXmlWriter.cs:1092
}
writer.ppStateInfo.ReturnState = State;
writer.currentState = ExpandPositionalParameters.State;
}
else
{
writer.currentState = InMember.State;
}
}
public override void WriteEndObject(XamlXmlWriter writer)
{
Debug.Assert(writer.namespaceScopes.Count > 0);
Frame frame = writer.namespaceScopes.Pop();
if (frame.AllocatingNodeType != XamlNodeType.StartObject &&
frame.AllocatingNodeType != XamlNodeType.GetObject)
{
throw new InvalidOperationException(SR.Format(SR.XamlXmlWriterWriteNotSupportedInCurrentState, "WriteEndObject"));
}
if (!frame.IsObjectFromMember)
{
writer.output.WriteEndElement();
}
if (writer.namespaceScopes.Count > 0)
{
writer.currentState = InMemberAfterEndObject.State;
}
else
{
writer.Flush();
writer.currentState = End.State;
}
}
}View on GitHub (pinned to 81131a70a4)