dotnet/wpf · error · ArgumentException

SR.XamlMarkupExtensionWriterCannotWriteNonstringValue

Error message

SR.XamlMarkupExtensionWriterCannotWriteNonstringValue

What it means

XamlMarkupExtensionWriter translates XAML node streams into the '{MarkupExtension ...}' string form. Its WriteValue override only accepts strings because the textual serialization layer can only append string tokens; any other CLR value type would corrupt the output. .NET throws ArgumentException with resource key XamlMarkupExtensionWriterCannotWriteNonstringValue for any non-string value.

Solutions

  1. Convert the value to its string form before calling WriteValue, e.g. using TypeConverter or Convert.ToString / culture-invariant formatting
  2. Check `if (value is string)` before forwarding and handle non-strings via a TypeConverter for the member's XamlType
  3. If copying from a XamlXmlReader/XamlObjectReader stream, only forward string values; for Value nodes of other types, resolve the member's type converter first

Example fix

// before
writer.WriteValue(node.Value); // Value is boxed int 42
// after
var s = node.Value as string ?? TypeConverterFor(member).ConvertToInvariantString(node.Value);
writer.WriteValue(s);
Defensive patterns

Strategy: type-guard

Validate before calling

if (value is not string s)
    s = ResolveStringViaTypeConverter(member, value); // convert before writing
writer.WriteValue(s);

Type guard

static bool IsWritableValue(object v) => v is string;

Try / catch

try { writer.WriteValue(v); }
catch (ArgumentException ex) when (ex.Message.Contains("non-string") || ex.Message.Contains("XamlMarkupExtensionWriter")) { /* convert to string and retry */ }

Prevention

When it happens

Trigger: Calling XamlMarkupExtensionWriter.WriteValue(object) with a value that is not a System.String — e.g. an int, double, bool, enum, or object instance — typically when copying nodes from a XamlReader stream and forwarding the node value verbatim.

Common situations: Writing a generic XAML-to-markup-extension converter that replays node streams; numeric or boolean property values inside a markup extension such as '{StaticResource 5}' or '{x:Static SomeBool}'; adapters that assume WriteValue takes any object like most XamlWriter implementations do.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlMarkupExtensionWriter.cs:177

        {
            currentState.WriteStartMember(this, property);
        }

        public override void WriteEndMember()
        {
            currentState.WriteEndMember(this);
        }

        public override void WriteNamespace(NamespaceDeclaration namespaceDeclaration)
        {
            currentState.WriteNamespace(this, namespaceDeclaration);
        }

        public override void WriteValue(object value)
        {
            if (value is not string s)
            {
                throw new ArgumentException(SR.XamlMarkupExtensionWriterCannotWriteNonstringValue);
            }

            currentState.WriteValue(this, s);
        }

        private class Node
        {
            public XamlMember XamlProperty
            {
                get;
                set;
            }

            public XamlPropertySet Members
            {
                get;
                set;
            }

View on GitHub (pinned to 81131a70a4)