{"record":{"id":"83abf8e7a6609151","repo":"MemPalace/mempalace","slug":"valid-to-ended-r-is-before-valid-from-valid-fro","errorCode":null,"errorMessage":"valid_to={ended!r} is before valid_from={valid_from!r}; an inverted interval would be invisible to every KG query","messagePattern":"valid_to=(.+?) is before valid_from=(.+?); an inverted interval would be invisible to every KG query","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mempalace/knowledge_graph.py","lineNumber":359,"sourceCode":"        obj_id = self._entity_id(obj)\n        pred = predicate.lower().replace(\" \", \"_\")\n        ended = sanitize_iso_temporal(ended or date.today().isoformat(), \"ended\")\n\n        with self._lock:\n            conn = self._conn()\n            with conn:\n                rows = conn.execute(\n                    \"SELECT id, valid_from FROM triples \"\n                    \"WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL\",\n                    (sub_id, pred, obj_id),\n                ).fetchall()\n\n                for row in rows:\n                    valid_from = row[\"valid_from\"]\n                    if valid_from is not None and _temporal_end_key(ended) < _temporal_start_key(\n                        valid_from\n                    ):\n                        raise ValueError(\n                            f\"valid_to={ended!r} is before valid_from={valid_from!r}; \"\n                            \"an inverted interval would be invisible to every KG query\"\n                        )\n\n                conn.execute(\n                    \"UPDATE triples SET valid_to=? \"\n                    \"WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL\",\n                    (ended, sub_id, pred, obj_id),\n                )\n\n    def supersede(\n        self,\n        subject: str,\n        predicate: str,\n        old_obj: str,\n        new_obj: str,\n        at: str = None,\n        confidence: float = 1.0,","sourceCodeStart":341,"sourceCodeEnd":377,"githubUrl":"https://github.com/MemPalace/mempalace/blob/06cb6987f02610784fefbad4b2bd5d026d164ba6/mempalace/knowledge_graph.py#L341-L377","documentation":"Raised by KnowledgeGraph.end_fact() when the `ended` timestamp would close an open triple before that triple's stored valid_from. The method loads all open rows (valid_to IS NULL) for the subject/predicate/object and rejects if _temporal_end_key(ended) < _temporal_start_key(valid_from) for any of them, because the resulting inverted interval would be invisible to every query.","triggerScenarios":"kg.end_fact(\"Alice\", \"works_at\", \"Acme\", ended=\"2023-01-01\") when the open triple was recorded with valid_from=\"2024-01-01\" — the end precedes the recorded start.","commonSituations":"Backfilling history after the fact with a wrong end date; clock skew between the machine that recorded the fact and the one closing it; importing legacy data where the fact's start was already wrong (too late).","solutions":["Verify the stored start: query the triples table for the open row's valid_from","Correct `ended` to be >= the stored valid_from","If the stored valid_from itself is wrong, fix or delete that triple first (repair tooling), then end the fact"],"exampleFix":"# before\nkg.end_fact(\"Alice\", \"works_at\", \"Acme\", ended=\"2023-01-01\")  # open triple started 2024-01-01\n\n# after\nkg.end_fact(\"Alice\", \"works_at\", \"Acme\", ended=\"2024-07-01\")  # ended >= stored valid_from","handlingStrategy":"validation","validationCode":"rows = kg.query_open_triples(subject, predicate, obj)  # or SELECT valid_from WHERE valid_to IS NULL\nearliest = min((r[\"valid_from\"] for r in rows if r[\"valid_from\"]), default=None)\nif earliest and ended < earliest:\n    ended = earliest  # clamp, or fix upstream data","typeGuard":null,"tryCatchPattern":"try:\n    kg.end_fact(...)\nexcept ValueError as e:\n    if \"inverted interval\" in str(e):\n        # fetch stored valid_from, correct `ended`, retry\n        ...\n    raise","preventionTips":["Derive `ended` from the same clock/timezone that recorded valid_from","When backfilling history, verify stored starts before closing facts","Run the KG repair/consistency tooling before bulk end_fact operations"],"tags":["knowledge-graph","temporal","validation","date"],"backgroundTag":null,"analyzedSha":"06cb6987f02610784fefbad4b2bd5d026d164ba6","analyzedAt":"2026-08-15T03:03:36.213Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}