{"record":{"id":"9393b9d0accd58de","repo":"Humanizr/Humanizer","slug":"input-words-cannot-be-empty","errorCode":null,"errorMessage":"Input words cannot be empty.","messagePattern":"Input words cannot be empty\\.","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/WordsToNumber/CompoundScaleWordsToNumberConverter.cs","lineNumber":41,"sourceCode":"    {\n        if (!TryConvert(words, out var parsedValue, out var unrecognizedWord))\n        {\n            throw new ArgumentException($\"Unrecognized number word: {unrecognizedWord}\");\n        }\n\n        return parsedValue;\n    }\n\n    /// <inheritdoc />\n    public override bool TryConvert(string words, out long parsedValue) =>\n        TryConvert(words, out parsedValue, out _);\n\n    /// <inheritdoc />\n    public override bool TryConvert(string words, out long parsedValue, out string? unrecognizedWord)\n    {\n        if (string.IsNullOrWhiteSpace(words))\n        {\n            throw new ArgumentException(\"Input words cannot be empty.\");\n        }\n\n        var normalized = Normalize(words);\n        var negative = false;\n\n        // Negative handling is deliberately outside the main parser so the cardinal and ordinal\n        // rules can stay focused on the positive phrase grammar.\n        foreach (var negativePrefix in profile.NegativePrefixes)\n        {\n            if (!normalized.StartsWith(negativePrefix, StringComparison.Ordinal))\n            {\n                continue;\n            }\n\n            negative = true;\n            normalized = normalized[negativePrefix.Length..].Trim();\n            break;\n        }","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/WordsToNumber/CompoundScaleWordsToNumberConverter.cs#L23-L59","documentation":"This ArgumentException is thrown inside CompoundScaleWordsToNumberConverter.TryConvert when the input string is null, empty, or whitespace. Critically, it throws from the Try-variant — not just the throwing Convert — so callers who expect TryConvert/TryToNumber to return false on invalid input will instead receive an exception. The guard exists because an empty phrase has no parseable tokens and the downstream tokenizer would produce meaningless diagnostics.","triggerScenarios":"Calling ToNumber or TryToNumber on a string that is null, string.Empty, or contains only whitespace, for any locale backed by CompoundScaleWordsToNumberConverter.","commonSituations":"Passing user input from a text field without null/empty checks; chaining a ToNumber call on the result of a Trim that produced an empty string; deserialized or API-received payload where the field was omitted; nullable reference types not enforced at the boundary.","solutions":["Check string.IsNullOrWhiteSpace(words) before calling ToNumber or TryToNumber and handle the empty case explicitly.","Use a null-coalescing or guard clause at the entry point: if (string.IsNullOrWhiteSpace(input)) return;","Enable nullable reference types so the compiler warns when a possibly-null string reaches the call.","Treat empty input as a business-logic decision (zero, skip, or error) rather than letting it reach the parser."],"exampleFix":"// before\nlong value = userInput.ToNumber(culture);\n\n// after\nif (string.IsNullOrWhiteSpace(userInput))\n    return 0;\nlong value = userInput.ToNumber(culture);","handlingStrategy":"validation","validationCode":"if (string.IsNullOrWhiteSpace(words))\n    return 0;\nreturn words.ToNumber(culture);","typeGuard":"static bool IsNonEmpty(string? words) =>\n    !string.IsNullOrWhiteSpace(words);","tryCatchPattern":"// TryToNumber ALSO throws on empty input, so guard before calling\ntry\n{\n    return words.ToNumber(culture);\n}\ncatch (ArgumentException ex) when (ex.Message.Contains(\"cannot be empty\"))\n{\n    return 0;\n}","preventionTips":["Always guard with string.IsNullOrWhiteSpace before calling ToNumber or TryToNumber — the Try variant also throws on empty input.","Treat empty input as a business-logic decision at the call site rather than relying on the parser.","Enable nullable reference types to catch null propagation at compile time.","Validate at the trust boundary (API entry, deserialization) before data reaches Humanizer."],"tags":["argumentexception","words-to-number","compound-scale","null-empty-input","validation"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}