BerriAI/litellm · critical · ValueError
Could not resolve credentials token. Got None or non-string
Error message
Could not resolve credentials token. Got None or non-string token (type={type(_credentials.token).__name__}) What it means
This ValueError comes from `_handle_reauthentication_async`, the async retry path that reloads Google credentials after a "Reauthentication is needed" failure. After re-loading and refreshing credentials, the code validates that `_credentials.token` is a non-None string; a None or non-string token means the refreshed google-auth credentials object still cannot produce a usable OAuth bearer token. It indicates the credential source itself is broken (e.g. malformed service-account JSON, deleted key, or an auth library that returned no token), not just an expired token.
Source
Thrown at litellm/llms/vertex_ai/vertex_llm_base.py:832
credentials=credentials,
project_id=project_id,
credential_cache_key=credential_cache_key,
)
if project_id is None and isinstance(credential_project_id, str):
project_id = credential_project_id
cache_credentials: Final = json.dumps(credentials) if isinstance(credentials, dict) else credentials
resolved_cache_key: Final = (cache_credentials, project_id)
# Always overwrite — any pre-existing entry at the resolved key
# references the OLD credentials object we just replaced, and
# leaving it would force the next request to do a redundant
# refresh/reauth before realizing the cached creds are stale.
self._credentials_project_mapping[resolved_cache_key] = (
_credentials,
credential_project_id,
)
if _credentials.token is None or not isinstance(_credentials.token, str):
raise ValueError(
f"Could not resolve credentials token. Got None or non-string token (type={type(_credentials.token).__name__})"
)
if project_id is None:
raise ValueError("Could not resolve project_id")
return _credentials.token, project_id
except Exception as retry_error:
verbose_logger.error(
"Async reauthentication retry failed for project_id: %s. Original error: %s. Retry error: %s",
project_id,
error,
retry_error,
)
raise error
def get_access_token(
self,
credentials: VERTEX_CREDENTIALS_TYPES | None,View on GitHub (pinned to 77b7c6c40c)
Solutions
- Regenerate the service-account key and update the credentials file/env var (VERTEXAI_CREDENTIALS or GOOGLE_APPLICATION_CREDENTIALS), then restart the process.
- Validate the credentials file parses and the key exists: run `gcloud auth application-default login` or `gcloud iam service-accounts keys create` to produce a fresh key.
- Run `gcloud auth application-default print-access-token` in the same environment to confirm the ADC chain can mint a token.
- If passing `vertex_credentials` as a string, ensure it is the full JSON contents of the key file, not a file path.
Defensive patterns
Strategy: retry
Validate before calling
from google.oauth2 import service_account
from google.auth.transport.requests import Request
def creds_can_mint_token(creds) -> bool:
try:
creds.refresh(Request())
return isinstance(creds.token, str) and len(creds.token) > 0
except Exception:
return False Try / catch
try:
resp = await litellm.acompletion(model="vertex_ai/gemini-1.5-pro", messages=msgs)
except ValueError as e:
if "Could not resolve credentials token" in str(e):
# credential source is broken: refresh the source, then retry once
reload_credentials_from_secret_store()
resp = await litellm.acompletion(model="vertex_ai/gemini-1.5-pro", messages=msgs)
else:
raise Prevention
- Load service-account JSON fresh from your secret store at startup and pass it via vertex_credentials instead of relying on a long-lived local file.
- Monitor for 'Reauthentication is needed' log lines and treat them as a signal to rotate credentials.
- Run a token-refresh smoke test (creds.refresh(Request()); assert isinstance(creds.token, str)) in your healthcheck.
When it happens
Trigger: Long-running async workloads using Vertex AI where the cached credentials expired, the refresh raised "Reauthentication is needed", the cache was cleared, `load_auth` re-ran, but the resulting credentials object has `token is None` (never computed) or a non-string token; typical with externally-supplied credentials strings that are invalid JSON or reference a revoked private key.
Common situations: A corrupted or truncated GOOGLE_APPLICATION_CREDENTIALS file; a service-account key deleted in GCP console while the process was running; impersonated credentials whose source credential expired; mixing `vertex_credentials` strings that are dicts/paths rather than serialized JSON.
Related errors
- Timeout error occurred.
- Could not resolve credentials - either dynamically or from e
- Credentials are None after loading
- Failed to retrieve file {file_id} from provider: {str(e)}
- 'api_key' is required in litellm_params for WXO agents
AI-assisted analysis of BerriAI/litellm@77b7c6c40c (2026-08-18).
Data as JSON: /api/errors/37646ddd81e566c8.
Report an issue: GitHub.