{"record":{"id":"aa3f5a31d51d3de0","repo":"affaan-m/ECC","slug":"invalid-email-self-email","errorCode":null,"errorMessage":"Invalid email: {self.email}","messagePattern":"Invalid email: (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"warning","filePath":"skills/python-patterns/SKILL.md","lineNumber":346,"sourceCode":"user = User(\n    id=\"123\",\n    name=\"Alice\",\n    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","sourceCodeStart":328,"sourceCodeEnd":364,"githubUrl":"https://github.com/affaan-m/ECC/blob/01e15490f04e29cfefe3896951f43db46994d8ee/skills/python-patterns/SKILL.md#L328-L364","documentation":"A ValueError raised in User.__post_init__ when the email field does not contain an '@' character. It is a coarse format check executed automatically by the dataclass right after construction. The check only verifies presence of '@', not full RFC 5322 validity.","triggerScenarios":"Constructing User(email=..., age=...) with an email missing '@', an empty string, or None being coerced to the string 'None'. __post_init__ runs immediately after dataclass field assignment.","commonSituations":"Form input not trimmed/validated before being passed to the dataclass; CSV import where the email column is blank; None passed because an upstream field was optional but the dataclass field is typed str.","solutions":["Validate email format at the input/parsing boundary (e.g. with a regex or email_validator library) before constructing the dataclass.","Strip whitespace from the email before assignment.","Replace the '@-in-string' heuristic with a proper validator (pydantic.EmailStr or the email_validator package).","Make the dataclass field accept Optional[str] if None is legitimately possible, and validate explicitly."],"exampleFix":"# before\nif \"@\" not in self.email:\n    raise ValueError(f\"Invalid email: {self.email}\")\n\n# after: use a real email validator\nfrom email_validator import validate_email, EmailNotValidError\ntry:\n    self.email = validate_email(self.email, check_deliverability=False).normalized\nexcept EmailNotValidError as e:\n    raise ValueError(f\"Invalid email: {self.email}\") from e","handlingStrategy":"validation","validationCode":"import re\nEMAIL_RE = re.compile(r\"^[^@\\s]+@[^@\\s]+\\.[^@\\s]+$\")\ndef is_plausible_email(s: str) -> bool:\n    return isinstance(s, str) and bool(EMAIL_RE.match(s.strip()))\n\nif not is_plausible_email(email):\n    raise ValueError(f\"Invalid email: {email!r}\")","typeGuard":"def is_non_empty_str(v) -> bool:\n    return isinstance(v, str) and v.strip() != \"\"","tryCatchPattern":"try:\n    user = User(email=email, age=age)\nexcept ValueError as e:\n    return respond_400(field=\"email\", message=str(e))","preventionTips":["Validate at the API boundary before constructing domain objects.","Use pydantic or email_validator for real email validation.","Normalize (strip + lowercase) emails before validation and storage."],"tags":["python","validation","email","dataclass"],"backgroundTag":null,"analyzedSha":"01e15490f04e29cfefe3896951f43db46994d8ee","analyzedAt":"2026-08-13T00:31:08.655Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}