dotnet/wpf · error · InvalidOperationException

SR.BamlWriterNoInElement

Error message

SR.BamlWriterNoInElement: {0} {1}

What it means

WriteProperty must be called while the writer's record stack top is an ElementStart record. When the parent record type is anything else, the writer throws InvalidOperationException(SR.BamlWriterNoInElement, "WriteProperty", parentType), reporting the offending record type in the message. This enforces valid BAML structure: properties can only be written directly inside an element.

Solutions

  1. Ensure the last call was WriteStartElement (not WriteStartComplexProperty/array/list) before WriteProperty.
  2. Use WriteStartComplexProperty/WriteEndComplexProperty for nested property scopes rather than attempting WriteProperty inside them.
  3. Wrap property writes in a state check or assert that the current scope is an element.

Example fix

// before
writer.WriteStartComplexProperty("Grid.Children");
writer.WriteProperty("Width", "100"); // wrong scope
// after
writer.WriteStartElement("Button", "Button", "...");
writer.WriteProperty("Width", "100");
Defensive patterns

Strategy: try-catch

Validate before calling

void EnsureElementScope(BamlWriter w, Func<BamlRecordType> peek)
{
    if (peek() != BamlRecordType.ElementStart)
        throw new InvalidOperationException("WriteProperty requires ElementStart scope");
}

Try / catch

try { writer.WriteProperty(name, value); }
catch (InvalidOperationException ex) when (ex.Message.Contains("WriteProperty"))
{
    // recover: re-enter element scope or abort serialization
}

Prevention

When it happens

Trigger: Calling WriteProperty after WriteStartElement on a nested/complex property, after WriteEndComplexProperty without re-entering an element, after WriteEndDocument, or in any state where PeekRecordType() != BamlRecordType.ElementStart.

Common situations: Emitting a property while inside a complex property or array/IList scope; forgetting to close and reopen an element around properties; interleaving WriteProperty and WriteStartElement incorrectly in a hand-rolled serializer.

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/cd68991aebd1e115. Report an issue: GitHub.

Appendix: source

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

        /// Custom serialization record.  Note that for custom serialization
        /// to work, the assembly that contains the property's type must be 
        /// loaded. If custom serialization is not chosen, then
        /// write out a 'normal' record, which will cause type conversion to happen
        /// at load time from the stored string.
        /// </remarks>
        public void WriteProperty(
            string             assemblyName,
            string             ownerTypeFullName,
            string             propName,
            string             value,
            BamlAttributeUsage propUsage)
        {
            VerifyWriteState();
            
            BamlRecordType parentType = PeekRecordType();
            if (parentType != BamlRecordType.ElementStart)
            {
                throw new InvalidOperationException(SR.Format(SR.BamlWriterNoInElement,
                                                           "WriteProperty",
                                                           parentType.ToString()));
            }

            object dpOrPi;
            Type   declaringType;
            GetDpOrPi(assemblyName, ownerTypeFullName, propName, out dpOrPi, out declaringType);

            // Check if the value is a MarkupExtension.  If so it must be expanded into
            // a series of baml records.  Otherwise just write out the property.
            AttributeData data = _extensionParser.IsMarkupExtensionAttribute(
                                                        declaringType,    
                                                        propName,       
                                                    ref value,
                                                        0,       // No line numbers for baml
                                                        0,
                                                        0,
                                                        dpOrPi);

View on GitHub (pinned to 81131a70a4)