dotnet/wpf · error · XamlParseException

SR.ParserBadString

Error message

SR.ParserBadString: {0} {1}

What it means

A string-convertible BAML record (POD/deferrable content record) throws XamlParseException with SR.ParserBadString when its serializer reports ConvertString could not convert the Value to custom binary (converted == false). The record's string value cannot be represented in the BAML binary encoding for its ValueType.

Solutions

  1. Fix the offending string value in the XAML so the type's converter accepts it (message names the value and expected ValueType)
  2. Check the ValueType converter — ensure the value matches the documented format for that type
  3. Simplify the attribute (e.g. use a plain string key instead of a custom binary-convertible one)
  4. If a valid string still fails, verify the custom serializer/converter is registered and in sync with BamlRecordManager

Example fix

// before
<Window x:Key="{x:Static bad:key}" />
// after: use a converter-compatible value
<Window x:Key="MyWindowKey" />
Defensive patterns

Strategy: validation

Validate before calling

// validate the value converts before writing BAML
if (!canConvert(valueType, attributeValue))
    throw new XamlParseException($"Value '{attributeValue}' is not valid for {valueType.Name}");

Type guard

static bool IsValidString(Type targetType, string value) {
    try { TypeConverter c = TypeDescriptor.GetConverter(targetType); return c != null && c.IsValid(value); }
    catch { return false; }
}

Try / catch

try { CompileXaml(xaml); }
catch (XamlParseException ex) {
    log.Error($"Bad string attribute in XAML: {ex.Message}"); throw;
}

Prevention

When it happens

Trigger: Compiling XAML to BAML where a PODStringRecord's Value cannot be converted by the type's serializer via ConvertStringToCustomBinary/ConvertToString.

Common situations: Malformed attribute values in XAML for types with custom string/binary converters (e.g. KeyString, deferrable resource keys), typos in enumerated or specially formatted string values, culture-sensitive string formats.

Understand the failure class

Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Markup/BamlRecords.cs:2605

                // if it can convert.
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and
                //        BamlRecordManager code and must be kept in sync with them...
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value);
            }
            else if (SerializerType == typeof(XamlPathDataSerializer))
            {
                XamlSerializer serializer = new XamlPathDataSerializer();

                // If we custom serialize this particular value at this point, then see
                // if it can convert.
                // NOTE:  This is sensitive to changes in the BamlRecordWriter and
                //        BamlRecordManager code and must be kept in sync with them...
                converted = serializer.ConvertStringToCustomBinary(bamlBinaryWriter, Value);
            }

            if (!converted)
            {
                throw new XamlParseException(SR.Format(SR.ParserBadString, Value, ValueType.Name));
            }
        }

#if !PBTCOMPILER
        internal override void Copy(BamlRecord record)
        {
            base.Copy(record);

            BamlPropertyCustomWriteInfoRecord newRecord = (BamlPropertyCustomWriteInfoRecord)record;
            newRecord._valueId = _valueId;
            newRecord._valueType = _valueType;
            newRecord._value = _value;
            newRecord._valueMemberName = _valueMemberName;
            newRecord._serializerType = _serializerType;
            newRecord._typeContext = _typeContext;
        }
#endif

View on GitHub (pinned to 81131a70a4)