BerriAI/litellm · error · ValueError
Mavvrik FOCUS destination: {label} must be HTTPS, got scheme
Error message
Mavvrik FOCUS destination: {label} must be HTTPS, got scheme '{parsed.scheme}' What it means
_validate_gcs_url() is applied to URLs the Mavvrik API hands back (the signed upload URL and the resumable-session URI). It first requires scheme https; anything else raises with the offending scheme interpolated. This guards against a compromised or misbehaving server redirecting credential-bearing uploads to plaintext.
Source
Thrown at litellm/integrations/focus/destinations/mavvrik_destination.py:44
# 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}'"
)
class FocusMavvrikDestination(FocusDestination):
"""Upload FOCUS CSV exports to Mavvrik via GCS signed URL."""
def __init__(
self,
*,
prefix: str,
config: dict[str, Any] | None = None,
) -> None:
config = config or {}
api_key: Final = config.get("api_key")View on GitHub (pinned to 6c2dcb801b)
Solutions
- Report the incident to Mavvrik — their API returned a non-https upload URL.
- Check for intercepting proxies (corporate MITM, service mesh) that may rewrite response bodies.
- Upgrade LiteLLM/mavvrik integration in case a URL-normalization fix shipped.
- Retry the export once; transient API misconfigurations are usually short-lived.
Defensive patterns
Strategy: try-catch
Validate before calling
from urllib.parse import urlparse
def assert_https_upload_url(url: str) -> None:
if urlparse(url).scheme != "https":
raise SecurityAlert(f"Mavvrik returned non-https upload URL: {url[:60]}") Type guard
from urllib.parse import urlparse
def is_https_gcs_url(url: str) -> bool:
p = urlparse(url)
return p.scheme == "https" and (p.hostname or "").endswith("storage.googleapis.com") Try / catch
try:
await dest.deliver(content=csv, time_window=tw, filename="f.csv")
except (RuntimeError, ValueError) as e:
if "must be HTTPS" in str(e):
security_alert("Mavvrik returned a plaintext upload URL — possible MITM")
raise Prevention
- Monitor for this error: a non-https signed URL from a trusted API is a security signal, not a flake.
- Keep egress TLS-terminating proxies from rewriting response bodies on the storage.googleapis.com path.
When it happens
Trigger: The Mavvrik upload-url endpoint returns a signed URL like http://storage.googleapis.com/... (scheme http, gs:// etc.), and the destination then calls _get_signed_url or validates the session Location header.
Common situations: A Mavvrik API change or bug returning http URLs; a man-in-the-middle/proxy rewriting https to http; extremely rare in normal operation since GCS signed URLs are https — seeing this usually means the response was tampered with or the endpoint returned an error page whose 'url' field points elsewhere.
Related errors
- Mavvrik FOCUS destination: {label} must be a GCS endpoint (s
- MAVVRIK_API_ENDPOINT must be an HTTPS URL
- MAVVRIK_API_ENDPOINT host must be a Mavvrik domain (e.g. htt
- Mavvrik FOCUS destination: GCS session init failed ({init_re
- Mavvrik FOCUS destination: GCS session init missing Location
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/10566a36bc5ac009.
Report an issue: GitHub.