666ghj/MiroFish · error · ValueError

Zep search query must not be empty

Error message

Zep search query must not be empty

What it means

Raised by normalize_zep_search_query in backend/app/utils/zep.py when the query argument is a str but strips to an empty string (only whitespace). The function is a precondition guard for Zep Cloud's graph search endpoint, which rejects blank queries upstream; failing fast here gives a clearer error before any network call. It is a ValueError raised before any HTTP request.

Source

Thrown at backend/app/utils/zep.py:40

# Keep request behavior aligned with the zep-cloud 3.25.0 SDK default that
# MiroFish used before introducing the shared client. This is an internal
# integration policy, not a deployment setting users need to tune.
ZEP_HTTP_REQUEST_TIMEOUT_SECONDS = 60.0
# Zep ingestion is asynchronous and may take several minutes. Preserve the
# original GraphBuilder deadline while keeping it separate from HTTP timeout.
ZEP_INGESTION_WAIT_TIMEOUT_SECONDS = 600
MAX_ZEP_SEARCH_QUERY_CHARS = 400
MAX_ZEP_SEARCH_RESULTS = 50


def normalize_zep_search_query(query: Any) -> str:
    """Return a non-empty query within Zep Cloud's endpoint limit."""

    if not isinstance(query, str):
        raise ValueError("Zep search query must be a string")
    normalized = query.strip()
    if not normalized:
        raise ValueError("Zep search query must not be empty")
    return normalized[:MAX_ZEP_SEARCH_QUERY_CHARS]


def normalize_zep_search_limit(limit: Any) -> int:
    """Clamp a search result limit to the current Zep Cloud contract."""

    try:
        normalized = int(limit)
    except (TypeError, ValueError) as exc:
        raise ValueError("Zep search limit must be an integer") from exc
    if normalized < 1:
        raise ValueError("Zep search limit must be at least 1")
    return min(normalized, MAX_ZEP_SEARCH_RESULTS)


@lru_cache(maxsize=4)
def _cached_zep_client(api_key: str, timeout: float) -> Zep:
    return Zep(

View on GitHub (pinned to b5b53acc57)

Solutions

  1. Check query and query.strip() at the caller before invoking the search; return an empty result or re-prompt instead of calling the API.
  2. Validate user-supplied search text at the request boundary (422-style error) so blank input never reaches the Zep layer.
  3. Note the function also truncates to MAX_ZEP_SEARCH_QUERY_CHARS (400); pass pre-trimmed, reasonably sized queries so behavior is predictable.

Example fix

# before
results = zep_search(query=user_input)  # user_input = "   "

# after
if not user_input or not user_input.strip():
    return []
results = zep_search(query=user_input.strip())
Defensive patterns

Strategy: validation

Validate before calling

def is_valid_zep_query(query: Any) -> bool:
    return isinstance(query, str) and bool(query.strip())

Type guard

def is_non_empty_query(query: Any) -> TypeGuard[str]:
    return isinstance(query, str) and len(query.strip()) > 0

Try / catch

try:
    results = zep_search(query=q, limit=10)
except ValueError as e:
    if "must not be empty" in str(e):
        results = []  # blank query is a no-op
    else:
        raise

Prevention

When it happens

Trigger: Calling a Zep search wrapper that uses normalize_zep_search_query with query="", query=" ", or a string of only newlines/tabs. Any caller forwarding user text or LLM-generated text without a blank check hits this.

Common situations: A chat/RAG endpoint where the user submits an empty message; an agent loop passing an LLM-generated search string that happens to be whitespace; a config default of "" for a search term.

Related errors


AI-assisted analysis of 666ghj/MiroFish@b5b53acc57 (2026-08-14). Data as JSON: /api/errors/71e8e85894afeb52. Report an issue: GitHub.