dotnet/wpf · error · InvalidOperationException

SR.AttachedPropertyOnTypeConvertedOrStringProperty

Error message

SR.AttachedPropertyOnTypeConvertedOrStringProperty

What it means

When XamlObjectReader converts a property value to a string (via a type converter) it checks whether that value itself exposes attached-property content (GetAttachedProperties). If it does, the XAML output would lose those attached properties, which is unrepresentable in attribute/string form, so an InvalidOperationException names the property, value, and the offending attached property.

Solutions

  1. Remove attached-property setters from values that are serialized through a type converter or as strings, or move them to a container element in XAML.
  2. Change the property's serialization so the value is written as an object element (remove/replace the TypeConverter) so attached properties can be emitted as child elements.
  3. Set the attached properties in the XAML on the parent/other element rather than on the converted value.

Example fix

// before
canvas.Children.Add(text); // text has Canvas.Left set and is stored via TypeConverter string property
xamlText = tc.ConvertToString(text); // throws: attached properties lost
// after
// serialize text as an object element instead of a converted string
Canvas.SetLeft(text, 10); // move attached property usage to the element tree, not a string property
Defensive patterns

Strategy: validation

Validate before calling

static void EnsureNoAttachedProps(object value) {
  if (value is DependencyObject d) {
    foreach (var p in new[]{Canvas.LeftProperty, Canvas.TopProperty, Grid.RowProperty})
      if (d.ReadLocalValue(p) != DependencyProperty.UnsetValue)
        throw new InvalidOperationException("Attached properties set on a type-converted/string property value.");
  }
}

Try / catch

try { xaml = reader.ReadSubtree(); /* serialize */ }
catch (InvalidOperationException ex) when (ex.Message.Contains("attached")) { /* move attached properties or change serialization mode */ }

Prevention

When it happens

Trigger: Reading an object where property P's value is type-converted or written as a string, and that value has attached properties set (e.g. a string/converted value carrying Canvas.Left, Grid.Row, etc.) — ThrowIfPropertiesAreAttached with property != null (XamlObjectReader.cs:906-908).

Common situations: A custom TypeConverter that converts a complex object (with attached properties set on it) to a string; WPF types stored in a property with a converter attached while layout attached properties were applied to them; cloning objects between UI trees during serialization.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlObjectReader.cs:908

                    }
                    else
                    {
                        context.Instance = null;
                        valueInfo = ObjectMarkupInfo.ForObject(propertyValue, context, propertyConverter);
                    }
                }

                return valueInfo;
            }

            private static void ThrowIfPropertiesAreAttached(object value, XamlMember property, SerializerContext context)
            {
                var props = context.Runtime.GetAttachedProperties(value);
                if (props is not null)
                {
                    if (property is not null)
                    {
                        throw new InvalidOperationException(SR.Format(SR.AttachedPropertyOnTypeConvertedOrStringProperty, property.Name, value.ToString(), props[0].Key.ToString()));
                    }
                    else
                    {
                        throw new InvalidOperationException(SR.Format(SR.AttachedPropertyOnDictionaryKey, value.ToString(), props[0].Key.ToString()));
                    }
                }
            }

            // Reproduce the logic of System.ComponentModel.ReflectPropertyDescriptor.ShouldSerializeValue
            private static bool ShouldWriteProperty(object source, XamlMember property, SerializerContext context)
            {
                bool isReadOnly = !context.IsPropertyWriteVisible(property);

                if (!isReadOnly)
                {
                    object defaultValue;
                    if (GetDefaultValue(property, out defaultValue))
                    {

View on GitHub (pinned to 81131a70a4)