{"record":{"id":"3871fa8f4c6379a4","repo":"affaan-m/ECC","slug":"invalid-age-self-age","errorCode":null,"errorMessage":"Invalid age: {self.age}","messagePattern":"Invalid age: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"skills/python-patterns/SKILL.md","lineNumber":349,"sourceCode":"    email=\"alice@example.com\"\n)\n```\n\n### Data Classes with Validation\n\n```python\n@dataclass\nclass User:\n    email: str\n    age: int\n\n    def __post_init__(self):\n        # Validate email format\n        if \"@\" not in self.email:\n            raise ValueError(f\"Invalid email: {self.email}\")\n        # Validate age range\n        if self.age < 0 or self.age > 150:\n            raise ValueError(f\"Invalid age: {self.age}\")\n```\n\n### Named Tuples\n\n```python\nfrom typing import NamedTuple\n\nclass Point(NamedTuple):\n    \"\"\"Immutable 2D point.\"\"\"\n    x: float\n    y: float\n\n    def distance(self, other: 'Point') -> float:\n        return ((self.x - other.x) ** 2 + (self.y - other.y) ** 2) ** 0.5\n\n# Usage\np1 = Point(0, 0)\np2 = Point(3, 4)","sourceCodeStart":331,"sourceCodeEnd":367,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/python-patterns/SKILL.md#L331-L367","documentation":"A ValueError raised in User.__post_init__ when the age field is outside the inclusive range [0, 150]. It enforces a sanity bound on age immediately after the dataclass is constructed. Both negative ages and implausibly large values trip the check.","triggerScenarios":"Constructing User(email, age) with age < 0 (e.g. a default sentinel like -1), age > 150 (a typo or wrong unit such as months), or a non-integer that compares incorrectly.","commonSituations":"CSV/JSON import where age is missing and defaults to -1 or 999; birthdate computed incorrectly producing a negative age; age supplied in months instead of years; a string '42' that happens to compare but later breaks arithmetic.","solutions":["Coerce and validate age at the input boundary: int(age) inside a try/except, then range-check.","Use a sentinel like None for unknown age instead of -1, and adjust the field type to Optional[int].","Compute age from birthdate with a tested helper rather than accepting a raw number from the user.","If importing bulk data, log and quarantine rows that fail the range check instead of aborting the batch."],"exampleFix":"# before\nif self.age < 0 or self.age > 150:\n    raise ValueError(f\"Invalid age: {self.age}\")\n\n# after: explicit type guard and named bounds\nMIN_AGE, MAX_AGE = 0, 150\nif not isinstance(self.age, int):\n    raise TypeError(f\"age must be int, got {type(self.age).__name__}\")\nif not MIN_AGE <= self.age <= MAX_AGE:\n    raise ValueError(f\"age {self.age} outside [{MIN_AGE},{MAX_AGE}]\")","handlingStrategy":"validation","validationCode":"MIN_AGE, MAX_AGE = 0, 150\ndef is_valid_age(v) -> bool:\n    return isinstance(v, int) and not isinstance(v, bool) and MIN_AGE <= v <= MAX_AGE\n\nif not is_valid_age(age):\n    raise ValueError(f\"Invalid age: {age!r}\")","typeGuard":"from numbers import Integral\ndef is_int_in_range(v, lo, hi) -> bool:\n    return isinstance(v, Integral) and not isinstance(v, bool) and lo <= v <= hi","tryCatchPattern":"try:\n    user = User(email=email, age=age)\nexcept ValueError as e:\n    return respond_400(field=\"age\", message=str(e))","preventionTips":["Compute age from birthdate with a tested helper rather than trusting raw input.","Use None (Optional[int]) for unknown age instead of sentinels like -1.","Quarantine invalid rows during bulk import rather than aborting."],"tags":["python","validation","dataclass","range"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}