calesthio/OpenMontage · error · RuntimeError
Failed to load/refresh service-account credentials from {pat
Error message
Failed to load/refresh service-account credentials from {path}: {exc} What it means
RuntimeError wrapping any exception raised while loading the JSON key (service_account.Credentials.from_service_account_file) or refreshing it (creds.refresh(Request())). The chained original exception (`from exc`) carries the true cause: malformed JSON, missing scopes on the key, clock skew, revoked key, or network failure reaching Google's token endpoint.
Source
Thrown at tools/google_credentials.py:129
raise RuntimeError(
"Service-account auth requires the 'google-auth' package. "
"Install it with: pip install google-auth"
) from exc
path = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS")
if not path or not os.path.exists(path):
raise RuntimeError(
"GOOGLE_APPLICATION_CREDENTIALS is not set or points to a missing "
"file; cannot use service-account authentication."
)
try:
creds = service_account.Credentials.from_service_account_file(
path, scopes=scopes
)
creds.refresh(Request())
except Exception as exc: # noqa: BLE001 - re-raised as actionable message
raise RuntimeError(
f"Failed to load/refresh service-account credentials from {path}: {exc}"
) from exc
token = creds.token
if not token or not isinstance(token, str):
raise RuntimeError(
"Service-account credentials did not yield a valid access token."
)
project_id = getattr(creds, "project_id", None)
ret_project_id = str(project_id) if project_id is not None else None
return token, ret_project_id
View on GitHub (pinned to 95e1c3d0ab)
Solutions
- Read the tail of the chained exception text — it distinguishes JSON parse errors from network/401 failures.
- Validate the key file: it must be a service-account JSON with client_email and private_key fields: `python -c "import json;k=json.load(open(p));print(k['client_email'])"`.
- If refresh got 401/400 invalid_grant, re-download a fresh key from the console and update the env var; check the VM/service account is enabled.
- If it is a network error, verify outbound access to oauth2.googleapis.com:443 (proxy/cert settings).
Example fix
# before
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "key.yaml" # wrong format -> RuntimeError('Failed to load/refresh ...')
# after
import json, os
key_path = "service-account.json"
json.load(open(key_path))["client_email"] # fast structural validation
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = key_path Defensive patterns
Strategy: try-catch
Validate before calling
import json, os
from pathlib import Path
def key_file_plausible() -> bool:
p = Path(os.environ.get("GOOGLE_APPLICATION_CREDENTIALS", ""))
if not p.is_file():
return False
try:
data = json.loads(p.read_text())
except json.JSONDecodeError:
return False
return "client_email" in data and "private_key" in data Try / catch
try:
token, project = get_service_account_token()
except RuntimeError as e:
cause = e.__cause__
if cause and "invalid_grant" in str(cause):
rotate_key_file() # 401/invalid_grant -> refresh the key, then retry
elif cause and isinstance(cause, OSError):
check_network_egress("oauth2.googleapis.com")
raise Prevention
- Structurally validate the key JSON (client_email/private_key) at startup.
- Treat invalid_grant as a key-rotation event, not a code bug.
- Verify outbound HTTPS to oauth2.googleapis.com in proxied environments.
When it happens
Trigger: GOOGLE_APPLICATION_CREDENTIALS points to a file that is not a valid service-account JSON (human-readable key export, YAML, truncated download), the key's project/service account is disabled or deleted, or the refresh HTTP request fails (offline, proxy, DNS, SSL inspection).
Common situations: Pasting a Firebase/console key in the wrong format, expired or rotated keys still referenced, corporate proxies intercepting oauth2.googleapis.com, or system clock drift invalidating JWT assertions.
Related errors
- Service-account auth requires the 'google-auth' package. Ins
- GOOGLE_APPLICATION_CREDENTIALS is not set or points to a mis
- Service-account credentials did not yield a valid access tok
- FAL_KEY or FAL_AI_API_KEY required for image upload
- KLING_API_KEY is not set. Configure KLING_API_KEY for offici
AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15).
Data as JSON: /api/errors/dd8cdc548a21f1a3.
Report an issue: GitHub.