dotnet/wpf · error · XamlXmlWriterException

SR.ExpandPositionalParametersWithoutUnderlyingType…

Error message

SR.ExpandPositionalParametersWithoutUnderlyingType (objectXamlType.GetQualifiedName())

What it means

When expanding positional parameters (x:Arguments-style markup extension nodes), the writer needs the CLR type of the object to inspect constructor parameters. If the XamlType has no UnderlyingType, XamlXmlWriterException is thrown because expansion cannot proceed without reflection over the actual CLR type.

Solutions

  1. Ensure the XamlSchemaContext can resolve the type's CLR type (reference the assembly, use AssemblyLoadContext/assembly resolvers).
  2. Use a schema context with type mapping (e.g. XamlSchemaContext with reference assemblies) instead of a bare context.
  3. Avoid positional-parameter expansion for unknown types by writing explicit x:Arguments members.
  4. Catch XamlXmlWriterException and fall back to non-expanded node output.

Example fix

// before
var sc = new XamlSchemaContext(); // cannot resolve underlying types
// after
var sc = new XamlSchemaContext(new[] { typeof(MyExtension).Assembly });
Defensive patterns

Strategy: type-guard

Validate before calling

if (objectXamlType.UnderlyingType is null) throw new InvalidOperationException("Cannot expand positional parameters without a CLR underlying type");

Type guard

bool CanExpand(XamlType t) => t?.UnderlyingType is not null;

Try / catch

try { writer.Close(); } catch (XamlXmlWriterException ex) when (ex.Message.Contains("UnderlyingType")) { /* serialize without pp expansion */ }

Prevention

When it happens

Trigger: Closing a StartObject whose XamlType.UnderlyingType is null while positional-parameter expansion is active — typically types from a schema context without CLR type mapping (type-only schema contexts, forwarded/unloaded types).

Common situations: Using XamlSchemaContext without an assembly resolver so referenced types can't be loaded, serializing XAML for types in not-yet-referenced assemblies, markup extensions whose types come from a metadata-only context.

Understand the failure class

Background: "not installed", "pip install", "required for": how missing-dependency errors surface across open-source libraries — this error's family across 34 libraries.

Related errors


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

Appendix: source

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

            private ExpandPositionalParameters() { }

            public static WriterState State
            {
                get { return state; }
            }

            private void ExpandPositionalParametersIntoProperties(XamlXmlWriter writer)
            {
                Frame frame = writer.namespaceScopes.Peek();
                Debug.Assert(frame.AllocatingNodeType == XamlNodeType.StartObject);

                XamlType objectXamlType = frame.Type;
                Debug.Assert(objectXamlType is not null);

                Type objectClrType = objectXamlType.UnderlyingType;
                if (objectClrType is null)
                {
                    throw new XamlXmlWriterException(SR.Format(
                        SR.ExpandPositionalParametersWithoutUnderlyingType, objectXamlType.GetQualifiedName()));
                }

                int numOfParameters = writer.ppStateInfo.NodesList.Count;

                ParameterInfo[] constructorParameters = GetParametersInfo(objectXamlType, numOfParameters);
                List<XamlMember> ctorArgProps = GetAllPropertiesWithCAA(objectXamlType);

                // If there aren't the same number of parameters then we throw
                if (constructorParameters.Length != ctorArgProps.Count)
                {
                    throw new XamlXmlWriterException(SR.ConstructorNotFoundForGivenPositionalParameters);
                }

                for (int i = 0; i < constructorParameters.Length; i++)
                {
                    ParameterInfo paraminfo = constructorParameters[i];

View on GitHub (pinned to 81131a70a4)