dotnet/wpf · error · ArgumentException

SR.NonclientClassnameCannotBeUsedWithFlagsOrImagename

Error message

SR.NonclientClassnameCannotBeUsedWithFlagsOrImagename

What it means

AddToProxyDescriptionTable special-cases pseudo-proxy class names (non-client-area proxies like scroll bars); for these, providing an ImageName or non-zero Flags is rejected with ArgumentException(SR.NonclientClassnameCannotBeUsedWithFlagsOrImagename). Pseudo-proxy class names must be matched solely by class name.

Solutions

  1. Set ImageName to null and Flags to 0 (ClientSideProviderMatchFlags.None) for the provider description targeting the pseudo-proxy class name.
  2. If you need ImageName/Flags matching, use a different ClassName that is not one of the reserved pseudo-proxy class names.
  3. Review your ClientSideProviderDescription table and separate nonclient pseudo-proxy registrations from ordinary hwnd proxy registrations.

Example fix

// before
new ClientSideProviderDescription(Factory, @"C:\my.dll", "#32768", ClientSideProviderMatchFlags.Substring)
// after
new ClientSideProviderDescription(Factory, null, "#32768", ClientSideProviderMatchFlags.None)
Defensive patterns

Strategy: validation

Validate before calling

bool isPseudoProxy = pseudoClassNames.Contains(desc.ClassName);
if (isPseudoProxy && (desc.ImageName != null || desc.Flags != 0)) throw new ArgumentException("Pseudo-proxy class names cannot use ImageName/Flags");

Type guard

static bool IsValidProxyDescription(ClientSideProviderDescription d) =>
  !(reservedPseudoProxyClassNames.Contains(d.ClassName) && (d.ImageName != null || d.Flags != 0));

Try / catch

try { ClientSettings.RegisterClientSideProviders(table); }
catch (ArgumentException ex) { log.Error($"Invalid provider description: {ex.Message}"); }

Prevention

When it happens

Trigger: Calling ClientSettings.RegisterClientSideProviders / SetProxyDescriptionTable with a ClientSideProviderDescription whose ClassName equals one of the known pseudo-proxy class names (e.g., nonclient class names) while ImageName is non-null or Flags != 0.

Common situations: Developers writing custom proxies for nonclient UI (scroll bars, title bars) who copy a normal proxy registration and also set an image/module filter or match flags; accidental reuse of a generic provider entry for a pseudo-proxy class name.

Understand the failure class

Background: Conflicting config options: "cannot be used together" — configuration validation errors across open-source libraries — this error's family across 162 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClient/MS/Internal/Automation/ProxyManager.cs:729

            // the array that is passed in may have the same className occuring more than once in the table.
            // The way this works it the first occurence in the array is giver the first chance to return a valid
            // proxy.  In order to make that work we go through the array backwards so the the entries first
            // in the table get inserted in front of the ones that came later.  This also works if 
            // RegisterWindowHandlers is called more than once.
            for( int i = proxyInfo.Length - 1;  i >= 0; i-- )
            {
                pi = proxyInfo[i];

                // Check for pseudo-proxy names...
                if( pi.ClassName != null && pi.ClassName.Length > 0 && pi.ClassName[ 0 ] == '#' )
                {
                    for( int j = 0 ; j < _pseudoProxyClassNames.Length ; j++ )
                    {
                        if( pi.ClassName.Equals( _pseudoProxyClassNames[ j ] ) )
                        {
                            if( pi.ImageName != null || pi.Flags != 0 )
                            {
                                throw new ArgumentException(SR.NonclientClassnameCannotBeUsedWithFlagsOrImagename);
                            }

                            _pseudoProxies[j] = pi.ClientSideProviderFactoryCallback;
                            break;
                        }
                    }
                    // fall through to add to table as usual, that ensures that it appears in a 'get' operation.
                }

                if( pi.ClassName == null && pi.ImageName == null )
                {
                    _fallbackHandlers.Insert(0, pi.ClientSideProviderFactoryCallback);
                }
                else if ( pi.ClassName == null )
                {
                    AddToHashTable(_imageOnlyHandlers, pi.ImageName, pi.ClientSideProviderFactoryCallback);
                }
                else if ((pi.Flags & ClientSideProviderMatchIndicator.AllowSubstringMatch) != 0)

View on GitHub (pinned to 81131a70a4)