{"record":{"id":"673df6fa7f1e1004","repo":"Humanizr/Humanizer","slug":"inflection-subject-has-an-unsupported-casing-exp","errorCode":null,"errorMessage":"Inflection {subject} has an unsupported casing expansion.","messagePattern":"Inflection (.+?) has an unsupported casing expansion\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/InflectionCatalogValidation.cs","lineNumber":240,"sourceCode":"        {\n            string normalized;\n            try\n            {\n                normalized = value.IsNormalized(NormalizationForm.FormC)\n                    ? value\n                    : value.Normalize(NormalizationForm.FormC);\n            }\n            catch (ArgumentException)\n            {\n                throw new InvalidOperationException(\n                    $\"Inflection {subject} contains invalid Unicode.\");\n            }\n\n            if (casing == \"lower-title-upper\")\n            {\n                if (!TryNormalizeSimpleLower(normalized, out var lower))\n                {\n                    throw new InvalidOperationException(\n                        $\"Inflection {subject} has an unsupported casing expansion.\");\n                }\n\n                normalized = lower;\n            }\n\n            var literal = allowStemPlaceholder\n                ? normalized.Replace(\"{stem}\", string.Empty)\n                : normalized;\n            if (literal.Length > 0 &&\n                !HasOnlyDeclaredScripts(literal, ownerScripts, allowNonLetters))\n            {\n                throw new InvalidOperationException(\n                    $\"Inflection {subject} contains text outside its declared scripts.\");\n            }\n\n            return normalized;\n        }","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer.SourceGenerators/Generators/ProfileCatalogs/InflectionCatalogValidation.cs#L222-L258","documentation":"For casing mode 'lower-title-upper', the validator calls TryNormalizeSimpleLower which walks each Unicode scalar and checks that the simple lowercasing does not change the string length (scalar width). If any scalar's simple-case mapping produces a different number of UTF-16 code units than the original, the casing expansion is rejected because it would break the stem-substitution invariant.","triggerScenarios":"An authored text contains a character whose Unicode simple-case mapping expands or contracts (e.g., a character that lowercases to a multi-code-unit sequence). TryNormalizeSimpleLower returns false when (lower scalar width) != (original scalar width) or (upper scalar width) != (original scalar width).","commonSituations":"Using characters with special casing behavior like the German eszett (ß), certain Greek sigma forms, or characters outside the BMP whose case mappings cross the surrogate boundary. Locale data that includes archaic or unusual scripts with non-width-preserving case mappings.","solutions":["Replace the problematic character with one whose simple lowercasing preserves scalar width, or use a casing mode other than 'lower-title-upper'.","If the character is essential, check whether InflectionUnicodeData pins it as a letter/mark with a width-preserving mapping, or file an issue to extend the pinned set.","Split the lexeme so the problematic form lives in a separate casing context."],"exampleFix":"# before — eszett expands when lowercased in some mappings\naccepted:\n  - 'STRAße'\n# after — use case-stable form or switch casing mode\naccepted:\n  - 'strasse'","handlingStrategy":"validation","validationCode":"# Before building, check for characters whose simple lowercasing changes scalar width.\npython3 -c \"\nimport unicodedata, sys\n# Flag known problematic characters for 'lower-title-upper' casing mode\nsuspects = {'\\u00DF':'LATIN SMALL LETTER SHARP S','\\u0130':'LATIN CAPITAL LETTER I WITH DOT ABOVE'}\nfor ch, name in suspects.items():\n    print(f'Caution: U+{ord(ch):04X} {name} may break width-preserving casing')\n\" src/Humanizer/Locales/*.yml","typeGuard":null,"tryCatchPattern":null,"preventionTips":["For 'lower-title-upper' casing mode, avoid characters like sharp-s (U+00DF) and capital I-with-dot (U+0130) whose case mappings change string length.","Use the precomposed or expanded form that preserves width across casing.","Test new locale text against TryNormalizeSimpleLower logic before committing."],"tags":["inflection","source-generator","casing","unicode","normalization","yaml","build-time"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}