{"record":{"id":"dec97b6cb1bd1565","repo":"HKUDS/Vibe-Trading","slug":"maturity-date-self-maturity-date-precedes-incept","errorCode":null,"errorMessage":"maturity_date {self.maturity_date} precedes inception_date {self.inception_date}","messagePattern":"maturity_date (.+?) precedes inception_date (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/entities/models.py","lineNumber":393,"sourceCode":"        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:\n            raise ValueError(\n                f\"coupon_frequency=0 marks a zero-coupon bond, but coupon_rate=\"\n                f\"{self.coupon_rate!r} is non-zero\"\n            )\n        object.__setattr__(self, \"coupon_frequency\", frequency)\n        if self.maturity_date is not None:\n            object.__setattr__(\n                self,\n                \"maturity_date\",\n                normalize_date(self.maturity_date, field_name=\"maturity_date\"),\n            )\n            if self.inception_date is not None and self.maturity_date < self.inception_date:\n                raise ValueError(\n                    f\"maturity_date {self.maturity_date} precedes inception_date \"\n                    f\"{self.inception_date}\"\n                )\n","sourceCodeStart":375,"sourceCodeEnd":397,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/entities/models.py#L375-L397","documentation":"Bond.__post_init__ normalizes maturity_date and rejects it when it precedes inception_date, since a bond cannot mature before it is issued. Both dates are normalized (via normalize_date) before the comparison.","triggerScenarios":"Bond(..., inception_date=date(2025,1,1), maturity_date=date(2024,1,1)); also date-format swaps (DD/MM vs MM/DD) that put maturity earlier, or a default far-past maturity (e.g. 1900-01-01) used as a placeholder.","commonSituations":"Day/month transposition when parsing international date formats; perpetual/undated instruments given a sentinel past date; loading dirty reference data with swapped columns.","solutions":["Correct the dates so maturity is on or after inception","For perpetuities/undated bonds, pass maturity_date=None if supported rather than a placeholder","Normalize date parsing to ISO format at ingest and cross-check maturity >= inception per row"],"exampleFix":"# before\nBond(instrument_id='b1', inception_date=date(2025,1,1), maturity_date=date(2024,6,1))\n\n# after\nBond(instrument_id='b1', inception_date=date(2024,6,1), maturity_date=date(2025,1,1))","handlingStrategy":"validation","validationCode":"from datetime import date\ninc = parse_iso(row['inception_date'])\nmat = parse_iso(row['maturity_date'])\nif mat is not None and inc is not None and mat < inc:\n    raise ValueError(f'maturity {mat} before inception {inc} on row {row_id}')\nBond(..., inception_date=inc, maturity_date=mat)","typeGuard":"def dates_ordered(inc, mat) -> bool:\n    return inc is None or mat is None or mat >= inc","tryCatchPattern":null,"preventionTips":["Parse dates as ISO (YYYY-MM-DD) unambiguously","Cross-check maturity >= inception during data profiling","Use None for undated/perpetual instruments instead of sentinel past dates"],"tags":["python","dataclass","bond","date-validation"],"backgroundTag":"date-order-validation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}