{"record":{"id":"1ebd0434a21ce5dd","repo":"Humanizr/Humanizer","slug":"cannot-safely-negate-long-minvalue","errorCode":null,"errorMessage":"Cannot safely negate long.MinValue.","messagePattern":"Cannot safely negate long\\.MinValue\\.","errorType":"exception","errorClass":"OverflowException","httpStatus":null,"severity":"error","filePath":"src/Humanizer/Localisation/NumberToWords/ConjunctionalScaleNumberToWordsConverter.cs","lineNumber":193,"sourceCode":"            }\n\n            parts.Add(string.Concat(\n                tens,\n                profile.TensUnitsSeparator,\n                GetUnitValue(units, isOrdinal)));\n            return;\n        }\n\n        parts.Add(GetUnitValue(number, isOrdinal));\n    }\n\n    string ConvertWholePhraseOrdinal(long number, bool addAnd)\n    {\n        if (number < 0)\n        {\n            if (number == long.MinValue)\n            {\n                throw new OverflowException(\"Cannot safely negate long.MinValue.\");\n            }\n\n            return $\"{profile.MinusWord} {ConvertWholePhraseOrdinal(-number, addAnd)}\";\n        }\n\n        if (number < profile.OrdinalUnitsMap.Length)\n        {\n            return GetUnitValue(number, isOrdinal: true);\n        }\n\n        return $\"{profile.OrdinalWholePhrasePrefix}{ConvertCore(number, isOrdinal: false, addAnd)}\";\n    }\n\n    string GetUnitValue(long number, bool isOrdinal) =>\n        isOrdinal ? profile.OrdinalUnitsMap[number] : profile.UnitsMap[number];\n\n    // \"and\" placement is modeled as a structural rule family rather than as locale branches.\n    // The generated profile says which insertion points are legal, and this method translates that","sourceCodeStart":175,"sourceCodeEnd":211,"githubUrl":"https://github.com/Humanizr/Humanizer/blob/ffc2b77c0f30d2fb176875841424379319d0ae9b/src/Humanizer/Localisation/NumberToWords/ConjunctionalScaleNumberToWordsConverter.cs#L175-L211","documentation":"OverflowException guard inside the WholePhrasePrefix ordinal path: negating long.MinValue is undefined in two's complement, so the renderer refuses it rather than producing a wrapped value. Note that the shipped public API is ConvertToOrdinal(int), and int.MinValue (cast to long) is never equal to long.MinValue, so this branch is currently unreachable through the public ordinal entry point; the guard is defensive for any future long-based ordinal caller of ConvertWholePhraseOrdinal.","triggerScenarios":"Not reachable via the public ConvertToOrdinal(int) API today, since int.MinValue != long.MinValue. Would only fire if a future overload invoked ConvertWholePhraseOrdinal(long.MinValue, addAnd) directly while OrdinalMode == WholePhrasePrefix.","commonSituations":"Not user-reachable in the current release; documented for completeness and for anyone extending the converter with a long ordinal overload.","solutions":["No action needed for the current int-based ordinal API.","If adding a long ordinal overload, reject long.MinValue at the entry point before delegating to ConvertWholePhraseOrdinal."],"exampleFix":null,"handlingStrategy":"validation","validationCode":"// Currently unreachable via ConvertToOrdinal(int); guard only if you add a long ordinal overload:\nstatic string SafeOrdinalWords(long number)\n{\n    if (number == long.MinValue)\n    {\n        throw new ArgumentOutOfRangeException(nameof(number), number, \"long.MinValue has no negatable ordinal form.\");\n    }\n    // ...delegate to the converter\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Do not extend ConvertWholePhraseOrdinal to long.MinValue without a guard.","When adding long ordinal overloads, reject long.MinValue at the entry point."],"tags":["number-to-words","overflow","defensive"],"backgroundTag":null,"analyzedSha":"ffc2b77c0f30d2fb176875841424379319d0ae9b","analyzedAt":"2026-08-13T21:42:34.584Z","schemaVersion":2},"datasetVersion":"2026-08-14T00:17:13.853Z"}