{"record":{"id":"4787927997e39cc8","repo":"mem0ai/mem0","slug":"invalid-query-must-be-a-non-empty-string-478792","errorCode":null,"errorMessage":"Invalid query: must be a non-empty string.","messagePattern":"Invalid query: must be a non-empty string\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"mem0/memory/main.py","lineNumber":247,"sourceCode":"            )\n    if top_k is not None:\n        if not isinstance(top_k, int) or isinstance(top_k, bool):\n            raise ValueError(\"top_k must be a valid integer\")\n        if top_k < 0:\n            raise ValueError(\n                f\"Invalid top_k: {top_k}. Must be a non-negative integer.\"\n            )\n\n\ndef _validate_and_trim_search_query(query: str) -> str:\n    \"\"\"\n    Validates and normalizes a search query before embedding/vector search.\n\n    Raises:\n        ValueError: If query is not a string or is empty/whitespace-only.\n    \"\"\"\n    if not isinstance(query, str):\n        raise ValueError(\"Invalid query: must be a non-empty string.\")\n    trimmed = query.strip()\n    if not trimmed:\n        raise ValueError(\"Invalid query: cannot be empty or whitespace-only.\")\n    return trimmed\n\n\ndef _is_sensitive_field(field_name: str) -> bool:\n    \"\"\"Check if a field should be redacted for telemetry safety.\n\n    Uses a layered approach:\n    1. Runtime fields (allowlist) — always preserved, highest priority.\n    2. Exact deny list — known secret field names.\n    3. Suffix deny list — catches patterns like db_password, auth_secret, etc.\n    \"\"\"\n    name = field_name.lower().strip()\n    if name in _RUNTIME_FIELDS:\n        return False\n    if name in _SENSITIVE_FIELDS_EXACT:","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/mem0ai/mem0/blob/001c235229be8795e3834520467bd0d661ed8f34/mem0/memory/main.py#L229-L265","documentation":"Raised by _validate_and_trim_search_query when the 'query' argument to Memory.search() is not a Python str at all (None, int, dict, list, bytes). The message text says 'non-empty string' but this specific branch fires for wrong types; the query must be a string because it is embedded and sent to the vector store as text. This is a fail-fast ValueError before any embedding cost.","triggerScenarios":"m.search(None, filters={'user_id':'u1'}); m.search(12345, ...); m.search({'question': '...'}, ...) passing a dict instead of its content; a variable that is None because an upstream LLM/tool call returned nothing; bytes from a network payload not decoded.","commonSituations":"Optional query parameters in a wrapper function defaulting to None and being forwarded anyway; template rendering returning None on failure; dataclass/JSON fields assumed to be strings but sometimes null.","solutions":["Guard with 'if not query: return []' (or raise your own domain error) before calling search().","Extract the actual string: m.search(payload['question'], ...) instead of m.search(payload, ...).","Coerce explicitly with str(query) only when you know the value is stringable text.","Default the parameter to a sensible sentinel and skip the search call when unset."],"exampleFix":"# before\nresult = m.search(user_question, filters=f)  # user_question may be None\n\n# after\nif not isinstance(user_question, str) or not user_question.strip():\n    return []\nresult = m.search(user_question, filters=f)","handlingStrategy":"type-guard","validationCode":"if not isinstance(query, str):\n    raise TypeError(f\"query must be str, got {type(query).__name__}\")","typeGuard":"def is_searchable_query(q) -> bool:\n    return isinstance(q, str) and len(q.strip()) > 0","tryCatchPattern":null,"preventionTips":["Treat query as a required parameter in your own wrapper signature (no default).","Check 'if not isinstance(q, str): return []' at the API edge (chat handler, tool entry).","Decode bytes payloads explicitly; never forward raw network objects."],"tags":["validation","search","query","typeerror"],"backgroundTag":null,"analyzedSha":"001c235229be8795e3834520467bd0d661ed8f34","analyzedAt":"2026-08-15T01:55:42.685Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}