dotnet/wpf · error · InvalidOperationException

SR.WhiteSpaceInCollection (deferredValue…

Error message

SR.WhiteSpaceInCollection (deferredValue, containingXamlType.Name)

What it means

In the deferred-value write path, a whitespace-only deferred string is rejected with InvalidOperationException naming the value and the containing XamlType, because the containing type is not a whitespace-significant collection. Same rule as the immediate WriteValue path, but applied to values buffered via writer.deferredValue.

Solutions

  1. Trim deferred values before they are buffered/flushed.
  2. Skip flushing values that are entirely whitespace when the containing type is not whitespace-significant.
  3. Add [WhitespaceSignificantCollection] to the containing collection type.
  4. Set xml:space="preserve" on the enclosing object so the significant-whitespace path is used.

Example fix

// before
writer.deferredValue = raw; // may be "  "
// after
writer.deferredValue = string.IsNullOrWhiteSpace(raw) ? null : raw.Trim();
Defensive patterns

Strategy: validation

Validate before calling

if (string.IsNullOrWhiteSpace(writer.deferredValue) && !GetContainingXamlType(writer).IsWhitespaceSignificantCollection) skipFlush = true;

Try / catch

try { FlushDeferred(writer); } catch (InvalidOperationException ex) when (ex.Message.Contains("whitespace")) { writer.deferredValue = null; }

Prevention

When it happens

Trigger: Flush of a deferred value where writer.deferredValue is all whitespace and GetContainingXamlType(writer) yields a XamlType without WhitespaceSignificantCollectionAttribute — e.g. whitespace captured then flushed in a non-collection member context.

Common situations: Round-tripping pretty-printed XAML whose indentation was captured as deferred content, writing whitespace between items of ordinary List<T> properties, custom writers deferring values for batching then flushing.

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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/System.Xaml/System/Xaml/XamlXmlWriter.cs:1492

                writer.currentState.WriteNamespace(writer, namespaceDeclaration);
            }

            public override void WriteEndMember(XamlXmlWriter writer)
            {
                if (writer.isFirstElementOfWhitespaceSignificantCollection)
                {
                    WriteXmlSpace(writer);
                    writer.output.WriteValue(writer.deferredValue);

                    writer.currentState = InMemberAfterValue.State;
                    writer.currentState.WriteEndMember(writer);

                    writer.isFirstElementOfWhitespaceSignificantCollection = false;
                }
                else
                {
                    XamlType containingXamlType = GetContainingXamlType(writer);
                    throw new InvalidOperationException(SR.Format(SR.WhiteSpaceInCollection, writer.deferredValue, containingXamlType.Name));
                }
            }

            public override void WriteObject(XamlXmlWriter writer, XamlType type, bool isObjectFromMember)
            {
                writer.output.WriteValue(writer.deferredValue);

                writer.currentState = InMemberAfterValue.State;
                writer.currentState.WriteObject(writer, type, isObjectFromMember);
            }
        }

        // Follows InObject after an End Object.
        // Like InMember but also allows End Member.
        //
        private class InMemberAfterEndObject : WriterState
        {
            private static WriterState state = new InMemberAfterEndObject();

View on GitHub (pinned to 81131a70a4)