BerriAI/litellm · error · ValueError

bucket_name must be provided for GCS destination

Error message

bucket_name must be provided for GCS destination

What it means

FocusGCSDestination's constructor reads bucket_name from its config dict and immediately raises if falsy before calling super().__init__ on GCSBucketBase. This is the destination-class-level guard; it normally fires only when the class is instantiated directly, bypassing the factory (the factory already enforces FOCUS_GCS_BUCKET_NAME).

Source

Thrown at litellm/integrations/focus/destinations/gcs_destination.py:29

    encode_gcs_object_name_for_url,
)

from .base import FocusDestination, FocusTimeWindow


class FocusGCSDestination(GCSBucketBase, FocusDestination):
    """Upload serialized Focus exports to GCS using the GCS JSON API."""

    def __init__(
        self,
        *,
        prefix: str,
        config: dict[str, Any] | None = None,
    ) -> None:
        config = config or {}
        bucket_name: Final = config.get("bucket_name")
        if not bucket_name:
            raise ValueError("bucket_name must be provided for GCS destination")
        super().__init__(bucket_name=bucket_name)
        service_account_json: Final = config.get("service_account_json")
        if service_account_json is not None:
            self.path_service_account_json = service_account_json
        self.prefix = prefix.rstrip("/")

    async def deliver(
        self,
        *,
        content: bytes,
        time_window: FocusTimeWindow,
        filename: str,
    ) -> None:
        object_name: Final = self._build_object_key(time_window=time_window, filename=filename)
        headers: Final = await self.construct_request_headers(service_account_json=self.path_service_account_json)
        headers["Content-Type"] = "application/octet-stream"
        encoded_name: Final = encode_gcs_object_name_for_url(object_name)
        url: Final = (

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Include bucket_name (bare bucket name, no gs:// scheme) in the config dict passed to FocusGCSDestination.
  2. Prefer using the destination factory, which also resolves env vars, instead of constructing the class directly.
  3. Validate the config dict keys before instantiation.

Example fix

# before
dest = FocusGCSDestination(prefix="focus", config={"bucket": "my-bucket"})

# after
dest = FocusGCSDestination(prefix="focus", config={"bucket_name": "my-bucket"})
Defensive patterns

Strategy: validation

Validate before calling

cfg = config or {}
if not cfg.get("bucket_name"):
    raise ValueError("FocusGCSDestination requires config['bucket_name'] (bare name, no gs:// scheme)")

Type guard

def is_valid_gcs_dest_config(config: dict | None) -> bool:
    return bool(config) and isinstance(config.get("bucket_name"), str) and bool(config["bucket_name"].strip()) and not config["bucket_name"].startswith("gs://")

Try / catch

try:
    dest = FocusGCSDestination(prefix=prefix, config=config)
except ValueError as e:
    if "bucket_name" in str(e):
        raise ConfigError("GCS destination misconfigured") from e
    raise

Prevention

When it happens

Trigger: Instantiating FocusGCSDestination(prefix=..., config={...}) directly with config missing 'bucket_name' or config=None; passing bucket under a different key like 'bucket' or 'gs://bucket' as a full URI instead of a bare name.

Common situations: Custom wiring that constructs the destination class instead of going through the factory; config dicts assembled from YAML where the key name drifted; passing the full gs:// URI rather than the bare bucket name.

Related errors


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