{"record":{"id":"faa895f5cd9f1a8f","repo":"Humanizr/Humanizer","slug":"linked-vigesimal-parser-profiles-require-descendin-faa895","errorCode":null,"errorMessage":"Linked-vigesimal parser profiles require descending scales.","messagePattern":"Linked-vigesimal parser profiles require descending scales\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Humanizer/Localisation/WordsToNumber/LinkedVigesimalWordsToNumberConverter.cs","lineNumber":498,"sourceCode":"\n    static string[] Tokenize(string value) =>\n        value.Split(' ', StringSplitOptions.RemoveEmptyEntries);\n\n    static string Normalize(string value) =>\n        string.Join(\" \", value.Trim().ToLowerInvariant().Split((char[]?)null, StringSplitOptions.RemoveEmptyEntries));\n\n    static LinkedVigesimalScale[] ValidateScales(LinkedVigesimalScale[] value)\n    {\n        for (var i = 0; i < value.Length; i++)\n        {\n            if (value[i].Value <= 0)\n            {\n                throw new InvalidOperationException(\"Linked-vigesimal parser profiles require positive scale values.\");\n            }\n\n            if (i > 0 && value[i - 1].Value <= value[i].Value)\n            {\n                throw new InvalidOperationException(\"Linked-vigesimal parser profiles require descending scales.\");\n            }\n        }\n\n        return value;\n    }\n}\n\n/// <summary>Pre-tokenized linked-vigesimal scale phrase.</summary>\nreadonly record struct TokenizedLinkedVigesimalScale(long Value, string[] OneTokens, string[] OneWithRemainderTokens, string[] NameTokens, string[] NameWithRemainderTokens);","sourceCodeStart":480,"sourceCodeEnd":507,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/WordsToNumber/LinkedVigesimalWordsToNumberConverter.cs#L480-L507","documentation":"This InvalidOperationException is thrown by LinkedVigesimalWordsToNumberProfile.ValidateScales (called from the profile constructor) when two adjacent scale rows are not strictly descending — i.e. when a later (smaller-position) scale has a value greater than or equal to the previous (larger) scale. The linked-vigesimal parser walks scales from largest to smallest and relies on this ordering to decompose numbers. The check fires at profile construction time, surfacing during locale registry initialization.","triggerScenarios":"Constructing a LinkedVigesimalWordsToNumberProfile with a scales array where any scale[i].Value is greater than or equal to scale[i-1].Value. This arises from locale YAML data with misordered or duplicate scale values.","commonSituations":"Editing locale YAML and accidentally swapping scale rows or duplicating a value; a locale generator sorting scales incorrectly; forking a locale and reordering entries; a merge conflict that scrambled scale ordering.","solutions":["Order scale values in strictly descending order in the locale YAML (e.g. 8000, 400, 20).","Regenerate the locale source from corrected YAML using the project's source generator.","Verify no duplicate scale values exist in the locale's scale list.","Add a CI test that constructs each locale profile to catch ordering violations early."],"exampleFix":"// before (locale YAML scales)\n//  - value: 20\n//  - value: 400   # out of order\n\n// after\n//  - value: 400\n//  - value: 20","handlingStrategy":"validation","validationCode":"// For locale authors: validate scale ordering before registration\nstatic bool ScalesAreDescending(long[] scales)\n{\n    for (var i = 1; i < scales.Length; i++)\n    {\n        if (scales[i - 1] <= scales[i])\n            return false;\n    }\n    return true;\n}","typeGuard":null,"tryCatchPattern":"try\n{\n    var converter = Configurator.GetWordsToNumberConverter(culture);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"descending scales\"))\n{\n    converter = Configurator.GetWordsToNumberConverter(fallbackCulture);\n}","preventionTips":["Order scale values strictly descending in locale YAML (e.g. 8000, 400, 20).","Ensure no duplicate scale values exist.","Run the locale test suite after any YAML or generator change.","Add CI tests that construct each locale profile to catch ordering violations."],"tags":["invalidoperation","locale-data","linked-vigesimal","scale-validation","profile-construction","configuration"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T05:17:29.042Z"}