{"record":{"id":"4e37fd3f74c21813","repo":"666ghj/MiroFish","slug":"zep-api-key-4e37fd","errorCode":null,"errorMessage":"ZEP_API_KEY 未配置","messagePattern":"ZEP_API_KEY 未配置","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"critical","filePath":"backend/app/utils/zep.py","lineNumber":76,"sourceCode":"    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.\n    if os.environ.get(\"ZEP_API_URL\"):\n        raise ValueError(\"ZEP_API_URL is unsupported; unset it to use Zep Cloud\")\n\n    normalized_key = (api_key or Config.ZEP_API_KEY or \"\").strip()\n    if not normalized_key:\n        raise ValueError(\"ZEP_API_KEY 未配置\")\n\n    request_timeout = float(\n        timeout if timeout is not None else ZEP_HTTP_REQUEST_TIMEOUT_SECONDS\n    )\n    if request_timeout <= 0:\n        raise ValueError(\"Zep request timeout must be greater than 0\")\n    return _cached_zep_client(normalized_key, request_timeout)\n\n\ndef clear_zep_client_cache() -> None:\n    \"\"\"Clear cached clients. Intended for tests and controlled reconfiguration.\"\"\"\n\n    _cached_zep_client.cache_clear()\n\n\ndef is_retryable_zep_error(error: BaseException) -> bool:\n    \"\"\"Return whether a failed *read* is safe and useful to retry.\"\"\"\n","sourceCodeStart":58,"sourceCodeEnd":94,"githubUrl":"https://github.com/666ghj/MiroFish/blob/b5b53acc57189a4a42e44a23e149dc655c98fe82/backend/app/utils/zep.py#L58-L94","documentation":"Raised by get_zep_client in backend/app/utils/zep.py when no API key resolves: the explicit api_key argument, then Config.ZEP_API_KEY, are all empty after .strip(). The Zep Cloud client cannot authenticate without a key, so construction is refused before _cached_zep_client is reached. The message is Chinese (\"ZEP_API_KEY is not configured\"), matching this project's config-error convention.","triggerScenarios":"Calling get_zep_client() with no argument while Config.ZEP_API_KEY is unset, empty, or whitespace-only; or .env exists but is loaded after Config reads the value.","commonSituations":"Fresh clone without .env; production deployment where the secret injection (Vault, K8s Secret, CI variable) was skipped; config imported before dotenv.load_dotenv() runs.","solutions":["Set ZEP_API_KEY in .env / process environment to a valid Zep Cloud key from the Zep console.","Verify load order: dotenv/config loading must happen before Config.ZEP_API_KEY is read.","To supply the key programmatically, call get_zep_client(api_key=\"zep-...\") directly — the explicit argument takes priority."],"exampleFix":"# before\nclient = get_zep_client()  # ZEP_API_KEY unset -> ValueError\n\n# after\n# .env: ZEP_API_KEY=zep_...\nload_dotenv()\nclient = get_zep_client()","handlingStrategy":"validation","validationCode":"def has_zep_credentials() -> bool:\n    return bool((Config.ZEP_API_KEY or \"\").strip())","typeGuard":null,"tryCatchPattern":"try:\n    client = get_zep_client()\nexcept ValueError as e:\n    if \"ZEP_API_KEY\" in str(e):\n        logger.error(\"Zep not configured; disabling memory features\")\n        raise\n    raise","preventionTips":["Add a startup/CI preflight that fails fast when ZEP_API_KEY is missing or blank.","Load .env before Config reads ZEP_API_KEY (check import order).","Wire the secret injector (K8s Secret, Vault, CI variable) and verify with a dry run."],"tags":["configuration","authentication","environment","zep","missing-api-key"],"backgroundTag":null,"analyzedSha":"b5b53acc57189a4a42e44a23e149dc655c98fe82","analyzedAt":"2026-08-14T22:29:33.146Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}