{"record":{"id":"857c936f33c7f8af","repo":"dotnet/wpf","slug":"sr-nonclientclassnamecannotbeusedwithflagsorimagename","errorCode":null,"errorMessage":"SR.NonclientClassnameCannotBeUsedWithFlagsOrImagename","messagePattern":"SR\\.NonclientClassnameCannotBeUsedWithFlagsOrImagename","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClient/MS/Internal/Automation/ProxyManager.cs","lineNumber":729,"sourceCode":"            // the array that is passed in may have the same className occuring more than once in the table.\n            // The way this works it the first occurence in the array is giver the first chance to return a valid\n            // proxy.  In order to make that work we go through the array backwards so the the entries first\n            // in the table get inserted in front of the ones that came later.  This also works if \n            // RegisterWindowHandlers is called more than once.\n            for( int i = proxyInfo.Length - 1;  i >= 0; i-- )\n            {\n                pi = proxyInfo[i];\n\n                // Check for pseudo-proxy names...\n                if( pi.ClassName != null && pi.ClassName.Length > 0 && pi.ClassName[ 0 ] == '#' )\n                {\n                    for( int j = 0 ; j < _pseudoProxyClassNames.Length ; j++ )\n                    {\n                        if( pi.ClassName.Equals( _pseudoProxyClassNames[ j ] ) )\n                        {\n                            if( pi.ImageName != null || pi.Flags != 0 )\n                            {\n                                throw new ArgumentException(SR.NonclientClassnameCannotBeUsedWithFlagsOrImagename);\n                            }\n\n                            _pseudoProxies[j] = pi.ClientSideProviderFactoryCallback;\n                            break;\n                        }\n                    }\n                    // fall through to add to table as usual, that ensures that it appears in a 'get' operation.\n                }\n\n                if( pi.ClassName == null && pi.ImageName == null )\n                {\n                    _fallbackHandlers.Insert(0, pi.ClientSideProviderFactoryCallback);\n                }\n                else if ( pi.ClassName == null )\n                {\n                    AddToHashTable(_imageOnlyHandlers, pi.ImageName, pi.ClientSideProviderFactoryCallback);\n                }\n                else if ((pi.Flags & ClientSideProviderMatchIndicator.AllowSubstringMatch) != 0)","sourceCodeStart":711,"sourceCodeEnd":747,"githubUrl":"https://github.com/dotnet/wpf/blob/81131a70a4c573cd62748a5c36908fc4d662daa9/src/Microsoft.DotNet.Wpf/src/UIAutomation/UIAutomationClient/MS/Internal/Automation/ProxyManager.cs#L711-L747","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Set ImageName to null and Flags to 0 (ClientSideProviderMatchFlags.None) for the provider description targeting the pseudo-proxy class name.","If you need ImageName/Flags matching, use a different ClassName that is not one of the reserved pseudo-proxy class names.","Review your ClientSideProviderDescription table and separate nonclient pseudo-proxy registrations from ordinary hwnd proxy registrations."],"exampleFix":"// before\nnew ClientSideProviderDescription(Factory, @\"C:\\my.dll\", \"#32768\", ClientSideProviderMatchFlags.Substring)\n// after\nnew ClientSideProviderDescription(Factory, null, \"#32768\", ClientSideProviderMatchFlags.None)","handlingStrategy":"validation","validationCode":"bool isPseudoProxy = pseudoClassNames.Contains(desc.ClassName);\nif (isPseudoProxy && (desc.ImageName != null || desc.Flags != 0)) throw new ArgumentException(\"Pseudo-proxy class names cannot use ImageName/Flags\");","typeGuard":"static bool IsValidProxyDescription(ClientSideProviderDescription d) =>\n  !(reservedPseudoProxyClassNames.Contains(d.ClassName) && (d.ImageName != null || d.Flags != 0));","tryCatchPattern":"try { ClientSettings.RegisterClientSideProviders(table); }\ncatch (ArgumentException ex) { log.Error($\"Invalid provider description: {ex.Message}\"); }","preventionTips":["Register pseudo-proxy (nonclient) class names with ImageName = null and Flags = 0.","Keep reserved class names in a constant list and validate descriptions before registration.","Never reuse a generic provider entry (with image/flags filters) for nonclient class names."],"tags":["uiautomation","proxy","invalid-argument"],"backgroundTag":"conflicting-config-options","analyzedSha":"81131a70a4c573cd62748a5c36908fc4d662daa9","analyzedAt":"2026-09-14T10:12:48.479Z","contentChangedAt":"2026-09-14T10:12:48.479Z","schemaVersion":2},"datasetVersion":"2026-09-22T01:17:13.364Z"}