{"record":{"id":"f30d484019332938","repo":"Humanizr/Humanizer","slug":"input-words-cannot-be-empty-f30d48","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/ContractedScaleWordsToNumberConverter.cs","lineNumber":42,"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 parsing is kept outside the token state machine so the main loop can stay\n        // focused on contracted scale composition.\n        if (normalized.StartsWith(profile.MinusWord + \" \", StringComparison.Ordinal))\n        {\n            negative = true;\n            normalized = normalized[(profile.MinusWord.Length + 1)..].Trim();\n        }\n\n        if (TryParseCardinal(normalized, out var value))\n        {\n            parsedValue = value;\n            if (negative)\n            {","sourceCodeStart":24,"sourceCodeEnd":60,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/WordsToNumber/ContractedScaleWordsToNumberConverter.cs#L24-L60","documentation":"This ArgumentException is thrown inside ContractedScaleWordsToNumberConverter.TryConvert when the input is null, empty, or whitespace. Notably, it throws from the Try-variant (TryConvert / TryToNumber), not only from the throwing Convert method. Callers who expect TryToNumber to return false for blank input will instead receive an exception because the parser has no tokens to process.","triggerScenarios":"Calling ToNumber or TryToNumber with null, string.Empty, or a whitespace-only string on a locale backed by ContractedScaleWordsToNumberConverter.","commonSituations":"Unvalidated user text from an input field; trimmed strings that became empty; deserialized payloads with missing fields; nullable strings passed without a null check.","solutions":["Guard with string.IsNullOrWhiteSpace(words) before calling either ToNumber or TryToNumber.","Return early or use a sentinel value (0, null) for empty input at the call site.","Enable nullable reference types to catch null propagation at compile time."],"exampleFix":"// before\nlong value = raw.ToNumber(culture);\n\n// after\nlong value = string.IsNullOrWhiteSpace(raw) ? 0 : raw.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 — 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.","Handle empty input explicitly at the call site; do not rely on TryToNumber to return false for blanks.","Enable nullable reference types for compile-time null safety.","Validate at trust boundaries before data reaches the parser."],"tags":["argumentexception","words-to-number","contracted-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"}