BerriAI/litellm · error · ValueError

Missing Cloudflare API Key - A call is being made to cloudfl

Error message

Missing Cloudflare API Key - A call is being made to cloudflare but no key is set either in the environment variables or via params

What it means

The Cloudflare transformation's validate_environment refuses to proceed when api_key is None. LiteLLM normally resolves the key from CLOUDFLARE_API_KEY (or provider-specific params) before reaching this point, so this ValueError means no credential could be found anywhere for the cloudflare provider. No HTTP call is attempted.

Source

Thrown at litellm/llms/cloudflare/chat/transformation.py:76

        if trimmed.endswith("/ai/run"):
            verbose_logger.warning(
                "Cloudflare api_base ending in '/ai/run' is the legacy Workers AI path and no longer serves OpenAI-compatible requests; rewriting to the '/ai/v1' endpoint"
            )
            return f"{trimmed[: -len('/ai/run')]}/ai/v1"
        return api_base

    def validate_environment(
        self,
        headers: dict,
        model: str,
        messages: list[AllMessageValues],
        optional_params: dict,
        litellm_params: dict,
        api_key: str | None = None,
        api_base: str | None = None,
    ) -> dict:
        if api_key is None:
            raise ValueError(
                "Missing Cloudflare API Key - A call is being made to cloudflare but no key is set either in the environment variables or via params"
            )
        return super().validate_environment(
            headers=headers,
            model=model,
            messages=messages,
            optional_params=optional_params,
            litellm_params=litellm_params,
            api_key=api_key,
            api_base=api_base,
        )

    def get_error_class(self, error_message: str, status_code: int, headers: dict | httpx.Headers) -> BaseLLMException:
        return CloudflareError(
            status_code=status_code,
            message=error_message,
        )

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Set CLOUDFLARE_API_KEY in the environment with a valid Cloudflare API token (AI/Workers AI permissions enabled).
  2. Or pass the key per-call: litellm.completion(model='cloudflare/...', messages=[...], api_key='<token>').
  3. If using the LiteLLM proxy, add cloudflare to the environment_variables block in the config YAML.
  4. Confirm the token has the 'Workers AI' read permission in the Cloudflare dashboard, otherwise you will trade this error for a 403 next.

Example fix

# before
response = litellm.completion(model="cloudflare/@cf/meta/llama-3.1-8b-instruct", messages=[...])

# after
response = litellm.completion(
    model="cloudflare/@cf/meta/llama-3.1-8b-instruct",
    messages=[...],
    api_key=os.environ["CLOUDFLARE_API_KEY"],
)
Defensive patterns

Strategy: validation

Validate before calling

import os

api_key = os.environ.get("CLOUDFLARE_API_KEY") or os.environ.get("CLOUDFLARE_API_TOKEN")
if not api_key:
    raise SystemExit("Set CLOUDFLARE_API_KEY before calling cloudflare models")

Try / catch

try:
    resp = litellm.completion(model="cloudflare/...", messages=msgs, api_key=api_key)
except ValueError as e:
    if "Missing Cloudflare API Key" in str(e):
        raise RuntimeError("Cloudflare credentials not configured") from e
    raise

Prevention

When it happens

Trigger: Invoking a cloudflare/* model with neither CLOUDFLARE_API_KEY set in the environment nor api_key=... passed to the completion call; also triggered when the key is set but resolved to None (e.g. empty string handled upstream as unset).

Common situations: Missing CLOUDFLARE_API_KEY in deployment environments; rotating/renaming keys and forgetting this provider; assuming the generic OPENAI_API_KEY style fallback covers Cloudflare when only the account ID was configured.

Related errors


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