{"record":{"id":"5171e7a34b80a967","repo":"django/django","slug":"max-whole-digits","errorCode":"max_whole_digits","errorMessage":"Ensure that there is no more than %(max)s digit before the decimal point.","messagePattern":"Ensure that there is no more than (.+?) digit before the decimal point\\.","errorType":"validation","errorClass":"ValidationError","httpStatus":null,"severity":"error","filePath":"django/core/validators.py","lineNumber":580,"sourceCode":"\n        if self.max_digits is not None and digits > self.max_digits:\n            raise ValidationError(\n                self.messages[\"max_digits\"],\n                code=\"max_digits\",\n                params={\"max\": self.max_digits, \"value\": value},\n            )\n        if self.decimal_places is not None and decimals > self.decimal_places:\n            raise ValidationError(\n                self.messages[\"max_decimal_places\"],\n                code=\"max_decimal_places\",\n                params={\"max\": self.decimal_places, \"value\": value},\n            )\n        if (\n            self.max_digits is not None\n            and self.decimal_places is not None\n            and whole_digits > (self.max_digits - self.decimal_places)\n        ):\n            raise ValidationError(\n                self.messages[\"max_whole_digits\"],\n                code=\"max_whole_digits\",\n                params={\"max\": (self.max_digits - self.decimal_places), \"value\": value},\n            )\n\n    def __eq__(self, other):\n        return (\n            isinstance(other, self.__class__)\n            and self.max_digits == other.max_digits\n            and self.decimal_places == other.decimal_places\n        )\n\n\n@deconstructible\nclass FileExtensionValidator:\n    message = _(\n        \"File extension “%(extension)s” is not allowed. \"\n        \"Allowed extensions are: %(allowed_extensions)s.\"","sourceCodeStart":562,"sourceCodeEnd":598,"githubUrl":"https://github.com/django/django/blob/ae25a40be07e8a749edf526df37c93e59d4a22c9/django/core/validators.py#L562-L598","documentation":"Raised by DecimalValidator.__call__ (django/core/validators.py:580) when whole_digits (digits before the decimal point = total digits minus decimals) exceeds (max_digits - decimal_places). This is the integer-portion capacity of the field; it is checked only when both max_digits and decimal_places are set.","triggerScenarios":"DecimalField(max_digits=5, decimal_places=2) permits 3 whole digits; Decimal('1234.56') has 4 whole digits and is rejected even though total digits (6) would only trip max_digits separately.","commonSituations":"Field capacity misjudged for the integer magnitude (e.g., a balance field that needs to hold millions); schema designed for small numbers later asked to store large ones; reporting rollups exceeding the per-row capacity.","solutions":["Increase max_digits (keeping decimal_places) to enlarge the whole-digit allowance, and migrate.","Reduce the integer magnitude (store in smaller units, or cap input).","If the value is always integral, use BigIntegerField instead of DecimalField."],"exampleFix":"// before\n# DecimalField(max_digits=5, decimal_places=2) -> 3 whole digits\nobj.amount = Decimal('1234.56')  # 4 whole digits -> rejected\n// after\n# migrate to DecimalField(max_digits=7, decimal_places=2) -> 5 whole digits\nobj.amount = Decimal('1234.56')","handlingStrategy":"validation","validationCode":"from decimal import Decimal\ndef fits_whole_digits(value, max_digits, decimal_places) -> bool:\n    d = Decimal(value)\n    if not d.is_finite():\n        return False\n    digits, exp = d.as_tuple()[1:]\n    total = len(digits) + (exp if exp > 0 else 0)\n    decimals = 0 if exp >= 0 else -exp\n    return (total - decimals) <= (max_digits - decimal_places)","typeGuard":"from decimal import Decimal\ndef is_within_whole_budget(value, max_digits: int, decimal_places: int) -> bool:\n    try:\n        d = Decimal(value)\n    except Exception:\n        return False\n    if not d.is_finite(): return False\n    digits, exp = d.as_tuple()[1:]\n    total = len(digits) + max(exp, 0)\n    decimals = 0 if exp >= 0 else -exp\n    return (total - decimals) <= (max_digits - decimal_places)","tryCatchPattern":"from django.core.exceptions import ValidationError\ntry:\n    validator(amount)\nexcept ValidationError as e:\n    if e.code == 'max_whole_digits':\n        raise ValueError(f'value exceeds whole-digit budget {max_digits - decimal_places}')\n    raise","preventionTips":["Plan whole-digit capacity (max_digits - decimal_places) for the largest realistic value.","Use BigIntegerField for pure integer monetary amounts (store cents).","Migrate proactively when business scale grows."],"tags":["decimal","validation","django"],"analyzedSha":"ae25a40be07e8a749edf526df37c93e59d4a22c9","analyzedAt":"2026-08-06T21:46:51.801Z","schemaVersion":2},"datasetVersion":"2026-08-07T03:17:09.362Z"}