BerriAI/litellm · error · ValueError

MAVVRIK_API_ENDPOINT must be an HTTPS URL

Error message

MAVVRIK_API_ENDPOINT must be an HTTPS URL

What it means

FocusMavvrikDestination validates the configured Mavvrik API endpoint before any network call. The very first check requires the string to start with 'https://' — anything else (http://, a bare hostname, a typo like htps://) is rejected immediately to prevent sending the API key over plaintext or to an unvalidated host.

Source

Thrown at litellm/integrations/focus/destinations/mavvrik_destination.py:33

from litellm._logging import verbose_logger
from litellm.llms.custom_httpx.http_handler import (
    AsyncHTTPHandler,
    get_async_httpx_client,
    httpxSpecialProvider,
)

from .base import FocusDestination, FocusTimeWindow

_MAVVRIK_ALLOWED_SUFFIXES: Final = (".mavvrik.dev", ".mavvrik.ai", ".mavvrik.app")

# GCS requires intermediate chunks to be a multiple of 256 KB.
# 8 MB gives a good balance between round-trips and memory pressure.
_GCS_CHUNK_SIZE: Final = 8 * 1024 * 1024  # 8 MB


def _validate_api_endpoint(api_endpoint: str) -> None:
    if not api_endpoint.startswith("https://"):
        raise ValueError("MAVVRIK_API_ENDPOINT must be an HTTPS URL")
    hostname: Final = (urlparse(api_endpoint).hostname or "").lower()
    if not any(hostname.endswith(suffix) for suffix in _MAVVRIK_ALLOWED_SUFFIXES):
        raise ValueError(
            "MAVVRIK_API_ENDPOINT host must be a Mavvrik domain (e.g. https://api.mavvrik.dev/<tenant_id>)"
        )


def _validate_gcs_url(url: str, label: str) -> None:
    parsed: Final = urlparse(url)
    if parsed.scheme != "https":
        raise ValueError(f"Mavvrik FOCUS destination: {label} must be HTTPS, got scheme '{parsed.scheme}'")
    hostname: Final = (parsed.hostname or "").lower()
    if not (hostname == "storage.googleapis.com" or hostname.endswith(".storage.googleapis.com")):
        raise ValueError(
            f"Mavvrik FOCUS destination: {label} must be a GCS endpoint (storage.googleapis.com), got '{hostname}'"
        )

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Use an https:// URL, e.g. https://api.mavvrik.dev/<tenant_id>.
  2. If testing locally against http, tunnel through an https endpoint (ngrok/tls proxy) — the check is strict by design.
  3. Normalize the value before saving it to config: if not endpoint.startswith('https://'): fix it at the source.

Example fix

# before
MAVVRIK_API_ENDPOINT=http://api.mavvrik.dev/acme

# after
MAVVRIK_API_ENDPOINT=https://api.mavvrik.dev/acme
Defensive patterns

Strategy: validation

Validate before calling

endpoint = os.getenv("MAVVRIK_API_ENDPOINT", "")
if not endpoint.startswith("https://"):
    raise SystemExit("MAVVRIK_API_ENDPOINT must start with https:// — refusing to send API key over plaintext")

Type guard

def is_https(url: str) -> bool:
    return url.startswith("https://")

Try / catch

try:
    dest = FocusMavvrikDestination(prefix=p, config=cfg)
except ValueError as e:
    if "HTTPS" in str(e):
        raise ConfigError("Mavvrik endpoint must be https") from e
    raise

Prevention

When it happens

Trigger: Passing api_endpoint='http://api.mavvrik.dev/...' or a scheme-less 'api.mavvrik.dev/tenant' in the mavvrik destination config / MAVVRIK_API_ENDPOINT env var when the destination is constructed.

Common situations: Local development endpoints using http; copy-pasting a hostname without the scheme; proxy rewrites stripping the scheme; internal test tenants configured with plain http.

Related errors


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