BCUninstaller/Bulk-Crap-Uninstaller · error · InvalidOperationException

Specified property is not of string type

Error message

Specified property is not of string type

What it means

Thrown by LocalisedNameAttribute.GetName() immediately after the property is found. It requires the resolved property's PropertyType to be exactly typeof(string); any other type (int, object, byte[], etc.) raises InvalidOperationException. This guards the subsequent (string)property.GetValue(null,null) cast.

Source

Thrown at source/KlocTools/Localising/LocalisedNameAttribute.cs:46

        private string ResourceName { get; }
        private Type ResourceType { get; }

        public string GetName()
        {
            if (NameOverride != null)
                return NameOverride;

            if ((ResourceType != null) && (ResourceName != null))
            {
                var property = ResourceType.GetProperty(ResourceName,
                    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
                if (property == null)
                {
                    throw new InvalidOperationException("Resource of this type doesn\'t contain specified property");
                }
                if (property.PropertyType != typeof (string))
                {
                    throw new InvalidOperationException("Specified property is not of string type");
                }
                return (string) property.GetValue(null, null);
            }
            return string.Empty;
        }
    }
}

View on GitHub (pinned to 608321de98)

Solutions

  1. Ensure the RESX entry for that key is a text/string value, not a file/binary resource.
  2. Rename the conflicting non-string resource and update ResourceName to a string-only key.
  3. If you need a typed resource, use ResourceManager.GetObject directly instead of this attribute.

Example fix

// before: RESX has "Logo" as System.Drawing.Bitmap
[LocalisedName(ResourceType = typeof(Strings), ResourceName = "Logo")] // throws

// after: add a string entry "LogoName" and reference it
[LocalisedName(ResourceType = typeof(Strings), ResourceName = "LogoName")]
Defensive patterns

Strategy: validation

Validate before calling

var prop = typeof(Strings).GetProperty(keyName,
    BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Static);
if (prop != null && prop.PropertyType != typeof(string))
    logger.Error($"Resource {keyName} is {prop.PropertyType}, expected string");

Type guard

static bool IsStringResource(Type resType, string key)
    => resType.GetProperty(key, BindingFlags.Public | BindingFlags.Static)?.PropertyType == typeof(string);

Try / catch

try { attr.GetName(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("not of string type"))
{ /* use member.Name as fallback */ }

Prevention

When it happens

Trigger: The ResourceName resolves to a resource property whose generated type is not string, e.g. a RESX entry typed as an image/icon/byte[] via the designer, or a manually added non-string static property on the resource class.

Common situations: Adding an image/file resource with the same key as a text resource, using a custom partial resource class that adds a non-string static member, or upgrading a resource whose type changed between versions.

Related errors


AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13). Data as JSON: /api/errors/df1b20f061900d89. Report an issue: GitHub.