{"record":{"id":"48b89ed1ca4584af","repo":"HKUDS/Vibe-Trading","slug":"face-value-must-be-positive-got-self-face-value","errorCode":null,"errorMessage":"face_value must be positive, got {self.face_value!r}","messagePattern":"face_value must be positive, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/entities/models.py","lineNumber":362,"sourceCode":"    face_value: float | None = None\n    coupon_rate: float | None = None\n    coupon_frequency: int = 2\n    maturity_date: date | None = None\n    day_count: str = \"30/360\"\n\n    def __post_init__(self) -> None:\n        \"\"\"Validate the base fields plus bond-specific ranges and consistency.\n\n        Raises:\n            ValueError: If ``face_value`` is non-positive, ``coupon_rate`` is\n                negative or expressed as a percentage, the coupon frequency\n                contradicts the coupon rate, or maturity precedes inception.\n        \"\"\"\n        super().__post_init__()\n        if self.face_value is not None:\n            face = float(self.face_value)\n            if face <= 0:\n                raise ValueError(f\"face_value must be positive, got {self.face_value!r}\")\n            object.__setattr__(self, \"face_value\", face)\n        if self.coupon_rate is not None:\n            rate = float(self.coupon_rate)\n            if rate < 0:\n                raise ValueError(f\"coupon_rate cannot be negative, got {rate!r}\")\n            if rate > 1.0:\n                raise ValueError(\n                    f\"coupon_rate must be a decimal fraction (0.05 means 5%), \"\n                    f\"got {rate!r}; a value above 1.0 is almost certainly a \"\n                    \"percentage\"\n                )\n            object.__setattr__(self, \"coupon_rate\", rate)\n        frequency = int(self.coupon_frequency)\n        if frequency < 0:\n            raise ValueError(\n                f\"coupon_frequency cannot be negative, got {self.coupon_frequency!r}\"\n            )\n        if self.coupon_rate and frequency == 0:","sourceCodeStart":344,"sourceCodeEnd":380,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/entities/models.py#L344-L380","documentation":"FixedIncome/Bond.__post_init__ requires face_value, when provided, to be strictly positive after float coercion, since a bond's par value cannot be zero or negative.","triggerScenarios":"Bond(..., face_value=0), face_value=-1000, or face_value supplied as 0.0 by a default/placeholder. Values are float()-coerced, so '1000' as a string works but 0/-5 does not.","commonSituations":"Missing par values defaulted to 0 in source files; a percent-of-par convention (0.98) confused with absolute par and multiplied out incorrectly; sign errors from short positions applied to the face field.","solutions":["Supply the actual positive par amount (commonly 1000 or 100)","If par is unknown, pass face_value=None rather than 0","Fix ingestion defaults so absent par fields become None, not zero"],"exampleFix":"# before\nBond(instrument_id='b1', face_value=0)\n\n# after\nBond(instrument_id='b1', face_value=1000)","handlingStrategy":"validation","validationCode":"face = row.get('face_value')\nface = float(face) if face not in (None, '', 0) else None\nif face is not None and face <= 0:\n    raise ValueError(f'bad face_value {face}')\nBond(..., face_value=face)","typeGuard":"def is_valid_face_value(f) -> bool:\n    return f is None or float(f) > 0","tryCatchPattern":null,"preventionTips":["Use None, not 0, for unknown par values","Sanity-check par magnitudes (typically 100 or 1000) during profiling"],"tags":["python","dataclass","bond","positive-value-validation"],"backgroundTag":"numeric-sign-validation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}