mem0ai/mem0 · error · ValueError

expiration_date must be a valid date in YYYY-MM-DD format.

Error message

expiration_date must be a valid date in YYYY-MM-DD format.

What it means

Raised by _normalize_expiration_date when the expiration_date argument to Memory.add() is a string that cannot be parsed by date.fromisoformat(). The OSS SDK supports automatic memory expiry, but only accepts a datetime/date object or a strict 'YYYY-MM-DD' string; anything else (e.g. '2026/08/14', '14-08-2026', ISO datetime with time '2026-08-14T00:00:00', or a typo) is rejected with a plain ValueError chained from the underlying parse failure.

Source

Thrown at mem0/memory/main.py:438


def _entity_collection_name(provider: str, collection_name: str) -> str:
    separator = "-" if provider == "s3_vectors" else "_"
    return f"{collection_name}{separator}entities"


def _normalize_expiration_date(value: Any) -> Optional[str]:
    if value is None:
        return None
    if isinstance(value, datetime):
        return value.date().isoformat()
    if isinstance(value, date):
        return value.isoformat()
    if isinstance(value, str):
        try:
            return date.fromisoformat(value).isoformat()
        except ValueError as exc:
            raise ValueError("expiration_date must be a valid date in YYYY-MM-DD format.") from exc
    raise ValueError("expiration_date must be a date string in YYYY-MM-DD format.")


def _payload_is_expired(payload: Optional[Dict[str, Any]]) -> bool:
    if not payload:
        return False
    expiration_date = payload.get("expiration_date")
    if not expiration_date:
        return False
    try:
        return date.fromisoformat(str(expiration_date)) < datetime.now(timezone.utc).date()
    except ValueError:
        return False


setup_config()
logger = logging.getLogger(__name__)

View on GitHub (pinned to 001c235229)

Solutions

  1. Format as date-only ISO: value.strftime('%Y-%m-%d') or value.date().isoformat().
  2. Pass a datetime.datetime or datetime.date object and let the SDK normalize it.
  3. Normalize frontend input with datetime.strptime(value, '%m/%d/%Y').date().isoformat() before calling add().
  4. Validate with date.fromisoformat(value) in your own layer to fail with your own error message.

Example fix

# before
m.add(msg, user_id="u1", expiration_date="2026/12/31")

# after
from datetime import datetime
m.add(msg, user_id="u1", expiration_date=datetime(2026, 12, 31))
# or: expiration_date="2026-12-31"
Defensive patterns

Strategy: validation

Validate before calling

from datetime import date, datetime
def normalize_expiration(value):
    if value is None:
        return None
    if isinstance(value, (datetime, date)):
        return value.isoformat()[:10]
    date.fromisoformat(value)  # raises early with a clear origin
    return value

Type guard

def is_valid_expiration(value) -> bool:
    if value is None:
        return True
    if isinstance(value, (datetime, date)):
        return True
    try:
        date.fromisoformat(value)
        return True
    except (ValueError, TypeError):
        return False

Prevention

When it happens

Trigger: m.add(msg, user_id='u1', expiration_date='2026/12/31') using slashes; expiration_date='31-12-2026' day-first European format; passing a full ISO datetime string (must pass a datetime object instead or date-only string); free-text like 'next year'; locale-formatted dates from a frontend.

Common situations: Frontend sending a JS Date.toISOString() string (which includes time) directly; user-typed dates in a form not normalized; date formatting with strftime('%d-%m-%Y') by mistake.

Related errors


AI-assisted analysis of mem0ai/mem0@001c235229 (2026-08-15). Data as JSON: /api/errors/4168881c532e53e2. Report an issue: GitHub.