BerriAI/litellm · error · ValueError

APISERPENT_API_KEY is not set. Set `APISERPENT_API_KEY` envi

Error message

APISERPENT_API_KEY is not set. Set `APISERPENT_API_KEY` environment variable.

What it means

Credential resolution for the apiserpent search provider. validate_headers resolves the API key from the caller-supplied api_key or the APISERPENT_API_KEY env var; if nothing resolves, a ValueError is raised before any HTTP call. The SerpApi-style search endpoint requires this key in the X-API-Key header.

Source

Thrown at litellm/llms/apiserpent/search/transformation.py:64

    def _is_deep_search(optional_params: dict) -> bool:
        return bool(optional_params.get(DEEP_SEARCH_PARAM))

    def validate_environment(
        self,
        headers: dict,
        api_key: str | None = None,
        api_base: str | None = None,
        **kwargs,
    ) -> dict:
        api_key = self.resolve_server_api_key(
            caller_api_key=api_key,
            caller_api_base=api_base,
            key_env_vars=("APISERPENT_API_KEY",),
            base_env_var="APISERPENT_API_BASE",
            default_api_base=APISERPENT_BASE,
        )
        if not api_key:
            raise ValueError("APISERPENT_API_KEY is not set. Set `APISERPENT_API_KEY` environment variable.")
        headers["X-API-Key"] = api_key
        headers["Content-Type"] = "application/json"
        return headers

    def get_complete_url(
        self,
        api_base: str | None,
        optional_params: dict,
        data: dict | list[dict] | None = None,
        **kwargs,
    ) -> str:
        """
        Build the search URL. APISerpent uses GET, so the transformed request is
        serialized into the query string. The endpoint path (quick vs deep) is
        always applied; an ``api_base`` / ``APISERPENT_API_BASE`` override only
        changes the host. The ``endswith`` guard keeps this idempotent, since the
        handler re-invokes this method with the already-resolved URL as api_base.
        """

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. export APISERPENT_API_KEY=your-key before starting the app.
  2. Or pass api_key explicitly on the call / in the model's litellm_params.
  3. If using dotenv, confirm load_dotenv() runs before the first search call.

Example fix

# before
results = litellm.search(query="litellm", web_search_provider="apiserpent")  # no key

# after
import os
os.environ["APISERPENT_API_KEY"] = "your-key"
results = litellm.search(query="litellm", web_search_provider="apiserpent")
Defensive patterns

Strategy: validation

Validate before calling

import os

def apiserpent_key_present() -> bool:
    return bool(os.getenv("APISERPENT_API_KEY"))

Try / catch

try:
    results = litellm.search(query=q, web_search_provider="apiserpent")
except ValueError as e:
    if "APISERPENT_API_KEY" in str(e):
        return http_error(503, "search provider not configured")
    raise

Prevention

When it happens

Trigger: Invoking apiserpent search without an api_key argument while APISERPENT_API_KEY is not exported in the process env. The API base can default fine (APISERPENT_BASE), but a missing key always aborts.

Common situations: New integration before the key was provisioned; key present in .env but the file not loaded (dotenv not run); CI jobs missing the secret; key named differently (e.g. SERPAPI_API_KEY) by mistake.

Related errors


AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15). Data as JSON: /api/errors/c2b3612f16bab19b. Report an issue: GitHub.