BerriAI/litellm · error · ValueError

GDC only accepts a GDCH service account credential as a JSON

Error message

GDC only accepts a GDCH service account credential as a JSON api_key (expected "type": "gdch_service_account"). Other Google credential types are rejected so their token or external-account endpoints cannot drive server-side requests.

What it means

The GDC (Google Distributed Cloud) transformation only accepts a service-account JSON whose top-level "type" is "gdch_service_account". _load_creds_from_key() parses the api_key as JSON and, if the type field is missing or is a different Google credential type (service_account, authorized_user, external_account, GCP ADC files), it raises this ValueError to prevent those credentials' token endpoints from being used for GDC server-side requests.

Source

Thrown at litellm/llms/gdc/chat/transformation.py:166

            gdch_creds: Final = self._gdch_creds_cache[cache_key]

            if not getattr(gdch_creds, "valid", False) or not getattr(gdch_creds, "token", None):
                self._fetch_auth(gdch_creds, ssl_verify)

            token: Final = gdch_creds.token

        return token

    def _load_creds_from_key(self, api_key: str) -> tuple[Any, bool]:
        import google.auth

        try:
            json_obj: Final = json.loads(api_key)
        except json.JSONDecodeError:
            return None, False
        if not isinstance(json_obj, dict) or json_obj.get("type") != self._GDCH_CREDENTIAL_TYPE:
            raise ValueError(
                "GDC only accepts a GDCH service account credential as a JSON api_key "
                '(expected "type": "gdch_service_account"). Other Google credential types are '
                "rejected so their token or external-account endpoints cannot drive server-side requests."
            )
        creds, _ = google.auth.load_credentials_from_dict(json_obj)
        return creds, True

    def validate_environment(
        self,
        headers: dict,
        model: str,
        messages: list[Any],
        optional_params: dict,
        litellm_params: dict,
        api_key: str | None = None,
        api_base: str | None = None,
    ) -> dict:
        import google.auth.exceptions

View on GitHub (pinned to 6c2dcb801b)

Solutions

  1. Obtain a GDCH service account JSON from the GDC console (its "type" is "gdch_service_account") and pass that file's contents as api_key.
  2. Verify before use: python -c "import json;print(json.load(open('key.json'))['type'])" must print gdch_service_account.
  3. If you intended Vertex/Gemini rather than Google Distributed Cloud, switch the model prefix (vertex_ai/ or gemini/) instead of forcing a GCP key into gdc/.

Example fix

# before (wrong credential type)
api_key = open("gcp_service_account.json").read()  # "type": "service_account"

# after
api_key = open("gdch_service_account.json").read()  # "type": "gdch_service_account"
Defensive patterns

Strategy: validation

Validate before calling

import json

def load_gdch_key(path: str) -> str:
    creds = json.load(open(path))
    if creds.get("type") != "gdch_service_account":
        raise ValueError(
            f"Wrong credential type {creds.get('type')!r}; need a GDCH service account"
        )
    return json.dumps(creds)

Type guard

def is_gdch_credential(api_key: object) -> bool:
    if not isinstance(api_key, str):
        return False
    try:
        obj = json.loads(api_key)
    except json.JSONDecodeError:
        return False
    return isinstance(obj, dict) and obj.get("type") == "gdch_service_account"

Try / catch

try:
    litellm.completion(model="gdc/...", messages=msgs, api_key=key_json)
except ValueError as e:
    if "gdch_service_account" in str(e):
        raise RuntimeError("Supply the GDCH service account JSON, not a GCP credential") from e
    raise

Prevention

When it happens

Trigger: Passing a regular GCP service-account JSON, a gcloud ADC credentials.json (type: authorized_user), or malformed JSON that parses but lacks type=gdch_service_account as the api_key for a gdc/ model.

Common situations: Developer reuses an existing GCP service account file because it 'looks like' the right JSON; copy-paste of application_default_credentials.json downloaded via gcloud auth application-default login; on-prem GDC install where the wrong service-account file was distributed.

Related errors


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