{"record":{"id":"8616030415cc736c","repo":"Humanizr/Humanizer","slug":"linked-vigesimal-parser-profiles-require-positive","errorCode":null,"errorMessage":"Linked-vigesimal parser profiles require positive scale values.","messagePattern":"Linked-vigesimal parser profiles require positive scale values\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"critical","filePath":"src/Humanizer/Localisation/WordsToNumber/LinkedVigesimalWordsToNumberConverter.cs","lineNumber":493,"sourceCode":"        new[] { terminalRemainderJoiner, terminalRemainderAlternateJoiner }\n            .Select(Tokenize)\n            .Where(static tokens => tokens.Length > 0)\n            .OrderByDescending(static tokens => tokens.Length)\n            .ToArray();\n\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":475,"sourceCodeEnd":507,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/WordsToNumber/LinkedVigesimalWordsToNumberConverter.cs#L475-L507","documentation":"This InvalidOperationException is thrown by LinkedVigesimalWordsToNumberProfile.ValidateScales (called from the profile constructor) when any scale row has a Value of zero or less. Scale values must be positive integers because they serve as multipliers and divisors in the parser. This is a locale-authoring invariant caught at profile construction time, meaning it fires during locale registry initialization — typically at application start or first use of the affected culture.","triggerScenarios":"Constructing a LinkedVigesimalWordsToNumberProfile with a scales array containing a row whose Value is 0 or negative. This arises from locale YAML data that has a missing, miscalculated, or corrupted scale value entry.","commonSituations":"Hand-editing locale YAML and accidentally leaving a scale value blank or zero; a locale generator emitting a default or placeholder value; corrupting a locale file during a merge or fork; a regression in the source generator's scale computation.","solutions":["Ensure every scale row in the locale YAML has a positive integer value.","Regenerate the locale source from corrected YAML using the project's source generator.","Audit the locale's scale definitions against the numeral system's expected progression.","Add a CI test that constructs each locale profile to catch invalid scale values early."],"exampleFix":"// before (locale YAML fragment)\n//  - value: 0\n\n// after\n//  - value: 20","handlingStrategy":"validation","validationCode":"// For locale authors: validate all scale values are positive\nstatic bool ScalesArePositive(long[] scales) =>\n    scales.All(static s => s > 0);","typeGuard":null,"tryCatchPattern":"try\n{\n    // Profile construction happens during locale registry init\n    var converter = Configurator.GetWordsToNumberConverter(culture);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"positive scale values\"))\n{\n    // Locale data is corrupt; use a fallback locale\n    converter = Configurator.GetWordsToNumberConverter(fallbackCulture);\n}","preventionTips":["Ensure every scale row in locale YAML has a positive integer value.","Run the locale test suite after any YAML change.","Regenerate locale source via the source generator rather than hand-editing generated code.","Add CI tests that construct each locale profile to catch invalid scale values."],"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"}