MemPalace/mempalace · error · ValueError
valid_to={ended!r} is before valid_from={valid_from!r}; an i
Error message
valid_to={ended!r} is before valid_from={valid_from!r}; an inverted interval would be invisible to every KG query What it means
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.
Source
Thrown at mempalace/knowledge_graph.py:359
obj_id = self._entity_id(obj)
pred = predicate.lower().replace(" ", "_")
ended = sanitize_iso_temporal(ended or date.today().isoformat(), "ended")
with self._lock:
conn = self._conn()
with conn:
rows = conn.execute(
"SELECT id, valid_from FROM triples "
"WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL",
(sub_id, pred, obj_id),
).fetchall()
for row in rows:
valid_from = row["valid_from"]
if valid_from is not None and _temporal_end_key(ended) < _temporal_start_key(
valid_from
):
raise ValueError(
f"valid_to={ended!r} is before valid_from={valid_from!r}; "
"an inverted interval would be invisible to every KG query"
)
conn.execute(
"UPDATE triples SET valid_to=? "
"WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL",
(ended, sub_id, pred, obj_id),
)
def supersede(
self,
subject: str,
predicate: str,
old_obj: str,
new_obj: str,
at: str = None,
confidence: float = 1.0,View on GitHub (pinned to 06cb6987f0)
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
Example fix
# before
kg.end_fact("Alice", "works_at", "Acme", ended="2023-01-01") # open triple started 2024-01-01
# after
kg.end_fact("Alice", "works_at", "Acme", ended="2024-07-01") # ended >= stored valid_from Defensive patterns
Strategy: validation
Validate before calling
rows = kg.query_open_triples(subject, predicate, obj) # or SELECT valid_from WHERE valid_to IS NULL
earliest = min((r["valid_from"] for r in rows if r["valid_from"]), default=None)
if earliest and ended < earliest:
ended = earliest # clamp, or fix upstream data Try / catch
try:
kg.end_fact(...)
except ValueError as e:
if "inverted interval" in str(e):
# fetch stored valid_from, correct `ended`, retry
...
raise Prevention
- 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
When it happens
Trigger: 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.
Common situations: 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).
Related errors
- valid_to={valid_to!r} is before valid_from={valid_from!r}; a
- {field_name} must be a string
- {field_name}={value!r} is not a valid ISO-8601 date or UTC d
- at={boundary!r} is before valid_from={valid_from!r}; an inve
- {type(self).name} does not advertise supports_namespace_isol
AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15).
Data as JSON: /api/errors/83abf8e7a6609151.
Report an issue: GitHub.