{"record":{"id":"5d2718e9f3b2b7be","repo":"Humanizr/Humanizer","slug":"indian-scale-form-number-profiles-require-dense-wo","errorCode":null,"errorMessage":"Indian scale-form number profiles require dense words for 0 through 99.","messagePattern":"Indian scale-form number profiles require dense words for 0 through 99\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/NumberToWords/IndianScaleFormNumberToWordsConverter.cs","lineNumber":143,"sourceCode":"    public string ZeroWord { get; } = zeroWord;\n    /// <summary>Gets the word used to prefix negative numbers.</summary>\n    public string NegativeWord { get; } = negativeWord;\n    /// <summary>Gets the suffix appended when no terminal replacement applies.</summary>\n    public string OrdinalSuffix { get; } = ordinalSuffix;\n    /// <summary>Gets dense cardinal words keyed by value.</summary>\n    public string[] DenseUnitsMap { get; } = ValidateDenseUnitsMap(denseUnitsMap);\n    /// <summary>Gets descending Indian grouping scale rows.</summary>\n    public IndianScaleForm[] Scales { get; } = ValidateScales(scales, denseUnitsMap.Length);\n    /// <summary>Gets exact ordinal words keyed by value.</summary>\n    public FrozenDictionary<int, string> OrdinalMap { get; } = ordinalMap ?? FrozenDictionary<int, string>.Empty;\n    /// <summary>Gets terminal cardinal-token replacements used to form ordinals.</summary>\n    public FrozenDictionary<string, string> OrdinalTerminalReplacements { get; } = ordinalTerminalReplacements ?? FrozenDictionary<string, string>.Empty;\n\n    static string[] ValidateDenseUnitsMap(string[] value)\n    {\n        if (value.Length < 100)\n        {\n            throw new InvalidOperationException(\"Indian scale-form number profiles require dense words for 0 through 99.\");\n        }\n\n        return value;\n    }\n\n    static IndianScaleForm[] ValidateScales(IndianScaleForm[] value, int denseUnitCount)\n    {\n        if (value.Length == 0 || value[^1].Value > denseUnitCount)\n        {\n            throw new InvalidOperationException(\"Indian scale-form number profiles require a scale value covered by the dense unit map range.\");\n        }\n\n        for (var i = 0; i < value.Length; i++)\n        {\n            if (value[i].Value <= 0)\n            {\n                throw new InvalidOperationException(\"Indian scale-form number profiles require positive scale values.\");\n            }","sourceCodeStart":125,"sourceCodeEnd":161,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/NumberToWords/IndianScaleFormNumberToWordsConverter.cs#L125-L161","documentation":"Profile constructor validation: DenseUnitsMap must have at least 100 entries (words for 0 through 99). Thrown at profile instantiation when the generated/locale data supplies fewer. This is a locale-authoring defect surfaced the first time the culture's converter is built (i.e. on first ToWords/ToOrdinalWords for that culture).","triggerScenarios":"First call to ToWords()/ToOrdinalWords() for an IndianScaleForm culture whose profile.denseUnitsMap has fewer than 100 elements; the constructor throws during converter resolution.","commonSituations":"Incomplete locale YAML providing only a partial dense map; a source-generator regression emitting a truncated map.","solutions":["Report the locale bug — dense words for 0-99 are required.","Use a locale/version with a complete dense unit map.","If authoring, provide dense words for 0 through 99 in the locale YAML."],"exampleFix":null,"handlingStrategy":"try-catch","validationCode":"// Construction-time validation throws when the converter is first resolved for the culture.\n// No public pre-check; isolate converter resolution so one bad locale does not poison the process.","typeGuard":null,"tryCatchPattern":"string words;\ntry\n{\n    words = value.ToWords(culture);\n}\ncatch (InvalidOperationException ex) when (ex.Message.Contains(\"dense words for 0 through 99\"))\n{\n    // Locale-data defect; fall back to a known-good culture.\n    words = value.ToWords(CultureInfo.InvariantCulture);\n}","preventionTips":["Run a one-shot converter-resolution smoke test for each locale at startup to surface construction errors early.","Pin Humanizer versions and regression-test locale construction after upgrades.","Report truncated dense maps upstream."],"tags":["number-to-words","profile-data","localization","construction-validation"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}