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
- Convert the value to its string form before calling WriteValue, e.g. using TypeConverter or Convert.ToString / culture-invariant formatting
- Check `if (value is string)` before forwarding and handle non-strings via a TypeConverter for the member's XamlType
- 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
- Always convert node values to strings (culture-invariant) before WriteValue in a markup extension writer
- Remember this writer only accepts strings, unlike generic XamlWriter implementations
- Test with numeric/bool/enum values inside markup extensions
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
- ArgumentException(SR.XamlXmlWriterCannotWriteNonstringValue…
- SR.Animation_ChildMustBeKeyFrame
- SR.Animation_ChildMustBeKeyFrame
- SR.Animation_ChildMustBeKeyFrame
- SR.Animation_ChildMustBeKeyFrame
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)