{"record":{"id":"c83712c37829fdce","repo":"666ghj/MiroFish","slug":"zep-search-limit-must-be-at-least-1","errorCode":null,"errorMessage":"Zep search limit must be at least 1","messagePattern":"Zep search limit must be at least 1","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"backend/app/utils/zep.py","lineNumber":52,"sourceCode":"    \"\"\"Return a non-empty query within Zep Cloud's endpoint limit.\"\"\"\n\n    if not isinstance(query, str):\n        raise ValueError(\"Zep search query must be a string\")\n    normalized = query.strip()\n    if not normalized:\n        raise ValueError(\"Zep search query must not be empty\")\n    return normalized[:MAX_ZEP_SEARCH_QUERY_CHARS]\n\n\ndef normalize_zep_search_limit(limit: Any) -> int:\n    \"\"\"Clamp a search result limit to the current Zep Cloud contract.\"\"\"\n\n    try:\n        normalized = int(limit)\n    except (TypeError, ValueError) as exc:\n        raise ValueError(\"Zep search limit must be an integer\") from exc\n    if normalized < 1:\n        raise ValueError(\"Zep search limit must be at least 1\")\n    return min(normalized, MAX_ZEP_SEARCH_RESULTS)\n\n\n@lru_cache(maxsize=4)\ndef _cached_zep_client(api_key: str, timeout: float) -> Zep:\n    return Zep(\n        api_key=api_key,\n        base_url=ZEP_CLOUD_BASE_URL,\n        timeout=timeout,\n    )\n\n\ndef get_zep_client(api_key: str | None = None, timeout: float | None = None) -> Zep:\n    \"\"\"Return a process-shared, explicitly configured Zep Cloud client.\"\"\"\n\n    # zep-cloud gives ZEP_API_URL precedence even when base_url is explicit.\n    # Reject it so this Cloud-only integration cannot silently target a\n    # self-hosted or compatibility endpoint.","sourceCodeStart":34,"sourceCodeEnd":70,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/utils/zep.py#L34-L70","documentation":"Raised by normalize_zep_search_limit in backend/app/utils/zep.py when limit converts to an int but is below 1 (0 or negative). Zep Cloud's search API requires limit >= 1, so the guard rejects degenerate values up front. After this check the value is clamped with min(normalized, MAX_ZEP_SEARCH_RESULTS) where MAX_ZEP_SEARCH_RESULTS=50, so anything >= 1 is safe.","triggerScenarios":"Passing limit=0 (common 'unset' sentinel mistake), negative values from arithmetic (page-size formulas that underflow), or user input \"0\"/\"-5\" parsed to int and forwarded.","commonSituations":"Caller uses 0 to mean 'no preference' expecting a default; a limit computed from page_size/offset math that can reach 0 or go negative on edge inputs.","solutions":["Coerce non-positive limits to a sensible default before calling: max(limit, 1) or replace 0/negatives with e.g. 10.","Validate user-supplied limit as an integer in 1..50 at the API boundary and reject out-of-range input there.","Never use 0 as an 'unset' sentinel for this API; resolve None yourself to a default."],"exampleFix":"# before\nresults = search(query=q, limit=requested)  # requested = 0\n\n# after\nlimit = requested if requested and requested > 0 else 10\nresults = search(query=q, limit=limit)","handlingStrategy":"validation","validationCode":"def safe_limit(raw: Any, default: int = 10) -> int:\n    try:\n        value = int(raw)\n    except (TypeError, ValueError):\n        return default\n    return value if value >= 1 else default","typeGuard":"def is_positive_limit(value: Any) -> TypeGuard[int]:\n    if isinstance(value, bool):\n        return False\n    try:\n        return int(value) >= 1\n    except (TypeError, ValueError):\n        return False","tryCatchPattern":"try:\n    limit = normalize_zep_search_limit(raw)\nexcept ValueError as e:\n    if \"at least 1\" in str(e):\n        limit = 1  # minimum meaningful page\n    else:\n        raise","preventionTips":["Clamp user-supplied limits to 1..50 at the request boundary (values above 50 are silently clamped to 50).","Do not use 0 as an 'unset' sentinel for limits.","Validate page-size arithmetic that derives limits — it can underflow to 0 or negative."],"tags":["validation","zep","pagination","bounds-check"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}