MemPalace/mempalace · error · ValueError

valid_to={valid_to!r} is before valid_from={valid_from!r}; a

Error message

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

What it means

Raised by KnowledgeGraph.add_fact() when the temporal interval is inverted: valid_to resolves to an instant strictly earlier than valid_from. Comparison uses _temporal_start_key/_temporal_end_key so legacy date-only values and canonical UTC datetimes compare correctly. The guard exists because every KG query filters on valid_from <= valid_to, so an inverted interval would be silently invisible.

Source

Thrown at mempalace/knowledge_graph.py:283

        Examples:
            add_triple("Max", "child_of", "Alice", valid_from="2015-04-01")
            add_triple("Max", "does", "swimming", valid_from="2025-01-01")
            add_triple("Alice", "worried_about", "Max injury", valid_from="2026-01-01")
        """

        valid_from = sanitize_iso_temporal(valid_from, "valid_from")
        valid_to = sanitize_iso_temporal(valid_to, "valid_to")

        # Reject inverted intervals. Use temporal comparison keys rather than
        # raw string comparison so legacy date-only values and canonical UTC
        # datetimes can safely coexist.
        if (
            valid_from is not None
            and valid_to is not None
            and _temporal_end_key(valid_to) < _temporal_start_key(valid_from)
        ):
            raise ValueError(
                f"valid_to={valid_to!r} is before valid_from={valid_from!r}; "
                "an inverted interval would be invisible to every KG query"
            )

        sub_id = self._entity_id(subject)
        obj_id = self._entity_id(obj)
        pred = predicate.lower().replace(" ", "_")

        # Auto-create entities if they don't exist
        with self._lock:
            conn = self._conn()
            with conn:
                conn.execute(
                    "INSERT OR IGNORE INTO entities (id, name) VALUES (?, ?)",
                    (sub_id, subject),
                )
                conn.execute(
                    "INSERT OR IGNORE INTO entities (id, name) VALUES (?, ?)",

View on GitHub (pinned to 06cb6987f0)

Solutions

  1. Check the caller: the two date arguments are almost certainly swapped
  2. Normalize both values through sanitize_iso_temporal yourself and compare before calling add_fact
  3. If the end is unknown, pass valid_to=None instead of guessing an early date
  4. Watch for timezone conversions that move a same-day interval across the date line

Example fix

# before
kg.add_fact("Alice", "works_at", "Acme", valid_from="2024-06-01", valid_to="2024-01-01")

# after
kg.add_fact("Alice", "works_at", "Acme", valid_from="2024-01-01", valid_to="2024-06-01")  # from <= to
Defensive patterns

Strategy: validation

Validate before calling

from mempalace.knowledge_graph import _temporal_end_key, _temporal_start_key  # or compare sanitized values

def valid_interval(valid_from, valid_to):
    return valid_to is None or valid_from is None or _temporal_end_key(valid_to) >= _temporal_start_key(valid_from)

if valid_interval(vf, vt):
    kg.add_fact(subj, pred, obj, valid_from=vf, valid_to=vt)

Try / catch

try:
    kg.add_fact(...)
except ValueError as e:
    if "inverted interval" in str(e):
        log.warning("dropping fact with bad dates: %s", e)
        return
    raise

Prevention

When it happens

Trigger: kg.add_fact("Alice", "works_at", "Acme", valid_from="2024-06-01", valid_to="2024-01-01") — any call where the end precedes the start, including mixed precision like valid_from="2024-06-01T00:00:00Z" with valid_to="2024-06-01" boundary handling.

Common situations: Swapping from/to arguments in caller code; user-typed date ranges entered backwards; timezone shifts (UTC vs local) pushing an end date before a start date; migrating data whose source system stored dates ambiguously.

Related errors


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