MemPalace/mempalace · error · ValueError

at={boundary!r} is before valid_from={valid_from!r}; an inve

Error message

at={boundary!r} is before valid_from={valid_from!r}; an inverted interval would be invisible to every KG query

What it means

Raised by KnowledgeGraph.supersede() when the `boundary` timestamp that should close the old fact precedes that old fact's stored valid_from. supersede() closes the open old triple at `boundary` and opens the successor at the same instant; a boundary before the old start would create an inverted, query-invisible interval.

Source

Thrown at mempalace/knowledge_graph.py:443

                for name, eid in ((subject, sub_id), (new_obj, new_id)):
                    conn.execute(
                        "INSERT OR IGNORE INTO entities (id, name) VALUES (?, ?)",
                        (eid, name),
                    )

                # Reject a boundary that precedes the old fact's start — an
                # inverted interval would be invisible to every KG query.
                rows = conn.execute(
                    "SELECT valid_from FROM triples "
                    "WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL",
                    (sub_id, pred, old_id),
                ).fetchall()
                for row in rows:
                    valid_from = row["valid_from"]
                    if valid_from is not None and _temporal_end_key(boundary) < _temporal_start_key(
                        valid_from
                    ):
                        raise ValueError(
                            f"at={boundary!r} is before valid_from={valid_from!r}; "
                            "an inverted interval would be invisible to every KG query"
                        )

                # Close the open old fact at the shared boundary.
                conn.execute(
                    "UPDATE triples SET valid_to=? "
                    "WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL",
                    (boundary, sub_id, pred, old_id),
                )

                # Open the successor at the same instant (idempotent if already open).
                existing = conn.execute(
                    "SELECT id FROM triples "
                    "WHERE subject=? AND predicate=? AND object=? AND valid_to IS NULL",
                    (sub_id, pred, new_id),
                ).fetchone()
                if existing:

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Look up the open old-fact triple's valid_from before superseding
  2. Set `at` to a boundary >= that valid_from (typically the real-world transition date)
  3. If the old fact's start is itself wrong, repair the triple directly rather than superseding with an invalid boundary

Example fix

# before
kg.supersede("Alice", "works_at", "Acme", "BizCo", at="2023-01-01")  # old fact started 2024-01-01

# after
kg.supersede("Alice", "works_at", "Acme", "BizCo", at="2024-07-01")  # boundary >= old valid_from
Defensive patterns

Strategy: validation

Validate before calling

# before superseding, ensure boundary >= old fact's start
old = kg.get_open_triple(subject, predicate, old_obj)  # returns valid_from
if old and old.valid_from and at < old.valid_from:
    raise ValueError(f"boundary {at} precedes old start {old.valid_from}")
kg.supersede(subject, predicate, old_obj, new_obj, at=at)

Try / catch

try:
    kg.supersede(...)
except ValueError as e:
    if "inverted interval" in str(e):
        # old fact started later than `at`; fix the boundary or repair the old triple
        ...
    raise

Prevention

When it happens

Trigger: kg.supersede("Alice", "works_at", "Acme", "BizCo", at="2023-01-01") when the open Acme triple has valid_from="2024-01-01".

Common situations: Correcting history with an effective date earlier than the originally recorded start; timezone or date-precision mismatches between the boundary and the stored start; replaying an event log out of order so a later supersede carries an earlier timestamp.

Related errors


AI-assisted analysis of MemPalace/mempalace@06cb6987f0 (2026-08-15). Data as JSON: /api/errors/41567611b5f9d35a. Report an issue: GitHub.