{"record":{"id":"fe3c31cb90b97584","repo":"Humanizr/Humanizer","slug":"scale-leading-compound-parser-profiles-require-pos","errorCode":null,"errorMessage":"Scale-leading compound parser profiles require positive scale values.","messagePattern":"Scale-leading compound parser profiles require positive scale values\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/WordsToNumber/ScaleLeadingCompoundWordsToNumberConverter.cs","lineNumber":436,"sourceCode":"        var maximum = 1;\n        foreach (var value in values)\n        {\n            maximum = Math.Max(maximum, Tokenize(value).Length);\n        }\n\n        return maximum;\n    }\n\n    static string[] Tokenize(string value) =>\n        value.Split(' ', StringSplitOptions.RemoveEmptyEntries);\n\n    static ScaleLeadingCompoundScale[] ValidateScales(ScaleLeadingCompoundScale[] value)\n    {\n        for (var i = 0; i < value.Length; i++)\n        {\n            if (value[i].Value <= 0)\n            {\n                throw new InvalidOperationException(\"Scale-leading compound parser profiles require positive scale values.\");\n            }\n\n            if (i > 0)\n            {\n                var previous = (ulong)value[i - 1].Value;\n                var current = (ulong)value[i].Value;\n                if (previous <= current || previous % current != 0)\n                {\n                    throw new InvalidOperationException(\"Scale-leading compound parser profiles require descending scales where each larger scale is divisible by the next smaller scale.\");\n                }\n            }\n        }\n\n        return value;\n    }\n}","sourceCodeStart":418,"sourceCodeEnd":452,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/WordsToNumber/ScaleLeadingCompoundWordsToNumberConverter.cs#L418-L452","documentation":"ScaleLeadingCompoundWordsToNumberProfile.ValidateScales throws this InvalidOperationException at line 436 when any scale value is zero or negative. The grammar multiplies counts by scale values, so non-positive scales are meaningless and rejected eagerly at profile construction. This is a locale-authoring/config defect surfaced during registry initialization.","triggerScenarios":"A locale scale ladder containing a 0 or negative value (typo, missing value, sign error in YAML). The throw occurs when the profile is constructed by the generator/registry, typically at first use of the culture.","commonSituations":"Adding a scale-leading locale with an incomplete scale entry; YAML parsing a missing number as 0; copy-paste leaving a placeholder; generator wiring bug.","solutions":["Ensure every scale value in the locale's scale ladder is a positive integer.","Regenerate locale source and run the locale tests.","Add an authoring test that constructs the profile and asserts no throw."],"exampleFix":"// before (profile scales)\nScales: [ 1000000, 0, 100 ]   // 0 <= 0 -> throws\n// after\nScales: [ 1000000, 1000, 100 ]","handlingStrategy":"validation","validationCode":"// Authoring guard: no scale value may be <= 0.\nstatic bool ScalesPositive(long[] scales) => scales.All(s => s > 0);","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Ensure every scale value is a positive integer in the locale data.","Regenerate source and run locale tests after scale edits.","Add a profile-construction unit test."],"tags":["words-to-number","scale-leading-compound","locale-authoring","config","invalidoperationexception"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}