BerriAI/litellm · error · RuntimeError
Mavvrik FOCUS destination: GCS session init missing Location
Error message
Mavvrik FOCUS destination: GCS session init missing Location header
What it means
A successful GCS resumable-upload session init (200/201) must return the session URI in the Location response header. If the header is absent or empty, the destination cannot proceed with chunked upload and raises. The session URI is subsequently validated to be an https GCS endpoint (errors 409/410).
Source
Thrown at litellm/integrations/focus/destinations/mavvrik_destination.py:195
metadata: Final = b'{"contentEncoding":"gzip","contentDisposition":"attachment"}'
init_resp: Final = await self._http.client.request(
method="POST",
url=signed_url,
headers={
"Content-Type": "application/gzip",
"x-goog-resumable": "start",
},
content=metadata,
timeout=30.0,
)
if init_resp.status_code not in (200, 201):
raise RuntimeError(
f"Mavvrik FOCUS destination: GCS session init failed ({init_resp.status_code}): {init_resp.text[:400]}"
)
session_uri: Final = init_resp.headers.get("Location")
if not session_uri:
raise RuntimeError("Mavvrik FOCUS destination: GCS session init missing Location header")
_validate_gcs_url(session_uri, "session URI")
verbose_logger.debug(
"Mavvrik FOCUS destination: GCS session started, uploading %d gzip bytes in %d chunk(s)",
total,
max(1, -(-total // _GCS_CHUNK_SIZE)), # ceiling division
)
# Step 2: upload in chunks; cancel session on any failure to avoid
# lingering GCS sessions (they stay open for ~1 week otherwise).
offset = 0
try:
while offset < total:
chunk = gzip_bytes[offset : offset + _GCS_CHUNK_SIZE]
chunk_end = offset + len(chunk) - 1
is_final = (offset + len(chunk)) >= total
content_range = f"bytes {offset}-{chunk_end}/{total}" if is_final else f"bytes {offset}-{chunk_end}/*"
expected_statuses = {200, 201} if is_final else {308}View on GitHub (pinned to 6c2dcb801b)
Solutions
- Check for intercepting proxies on the egress path and ensure the Location header is passed through unmodified.
- Retry the delivery — a fresh signed URL and session init may succeed.
- Verify the client hits storage.googleapis.com directly (no transparent rewriting) by dumping response headers in a manual test.
- Report to LiteLLM/Mavvrik if it persists with no proxy in the path.
Defensive patterns
Strategy: retry
Try / catch
try:
await mavvrik_dest.deliver(content=csv, time_window=tw, filename="f.csv")
except RuntimeError as e:
if "missing Location header" in str(e):
# likely a header-stripping proxy or transient GCS anomaly; a new session usually works
await asyncio.sleep(5)
await mavvrik_dest.deliver(content=csv, time_window=tw, filename="f.csv")
else:
raise Prevention
- Ensure egress proxies/meshes forward the Location response header from storage.googleapis.com.
- Test the full upload path (init → Location → chunk) in staging through the same network path as production.
When it happens
Trigger: GCS (or an intermediary) returns 200 to the x-goog-resumable start POST but omits the Location header — e.g. a proxy stripping redirect/Location headers, or an API-gateway response that doesn't forward GCS headers.
Common situations: Corporate proxies or service meshes (Envoy/ISTIO with header rewriting) stripping Location; rarely a GCS API anomaly. Pure direct-to-storage.googleapis.com traffic virtually never hits this.
Related errors
- Mavvrik FOCUS destination: {label} must be HTTPS, got scheme
- Mavvrik FOCUS destination: GCS session init failed ({init_re
- GCS upload failed: status={response.status_code} body={respo
- Mavvrik FOCUS destination: {label} must be a GCS endpoint (s
- Mavvrik FOCUS destination: register failed ({resp.status_cod
AI-assisted analysis of BerriAI/litellm@6c2dcb801b (2026-08-15).
Data as JSON: /api/errors/38f0d4e391f9462d.
Report an issue: GitHub.