calesthio/OpenMontage · error · RuntimeError

GOOGLE_APPLICATION_CREDENTIALS is not set or points to a…

Error message

GOOGLE_APPLICATION_CREDENTIALS is not set or points to a missing file; cannot use service-account authentication.

What it means

RuntimeError raised when the GOOGLE_APPLICATION_CREDENTIALS environment variable is unset or points to a path that does not exist on disk. The service-account flow needs a JSON key file, and this check runs before any network call so misconfiguration is reported immediately rather than as an opaque Google auth error.

Solutions

  1. Export the variable with an absolute path: `export GOOGLE_APPLICATION_CREDENTIALS=/abs/path/service-account.json`.
  2. Verify both conditions the code checks: `echo $GOOGLE_APPLICATION_CREDENTIALS` prints a path AND `test -f "$GOOGLE_APPLICATION_CREDENTIALS"` succeeds.
  3. In Docker/CI, ensure the env var is passed (-e / env: block) and the key file is actually mounted/copied into the container at that path.
  4. Use absolute paths — relative paths break when the process cwd differs.

Example fix

# before
subprocess.run(["python", "-m", "app"])  # env var not inherited -> RuntimeError

# after
import os
os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = str(key_path.resolve())
assert Path(os.environ["GOOGLE_APPLICATION_CREDENTIALS"]).is_file()
subprocess.run(["python", "-m", "app"], env=os.environ)
Defensive patterns

Strategy: validation

Validate before calling

import os
from pathlib import Path

def credentials_configured() -> bool:
    path = os.environ.get("GOOGLE_APPLICATION_CREDENTIALS")
    return bool(path) and Path(path).is_file()

Try / catch

try:
    token, project = get_service_account_token()
except RuntimeError as e:
    if "GOOGLE_APPLICATION_CREDENTIALS" in str(e):
        raise SystemExit("Set GOOGLE_APPLICATION_CREDENTIALS to an absolute key path") from e
    raise

Prevention

When it happens

Trigger: Invoking service-account auth with GOOGLE_APPLICATION_CREDENTIALS missing from the environment (env not exported, .env not loaded, different shell/deployment context) or set to a stale/moved/typo'd file path.

Common situations: Secrets set in a local shell but not passed to Docker/systemd/CI service context; the key file moved after rotation; relative path resolved from a different working directory; variable name typo (e.g. GOOGLE_APPLICATION_CREDENTIAL).

Understand the failure class

Related errors


AI-assisted analysis of calesthio/OpenMontage@95e1c3d0ab (2026-08-15). Data as JSON: /api/errors/adffbe6fc8184e1a. Report an issue: GitHub.

Appendix: source

Thrown at tools/google_credentials.py:118

    Raises:
        RuntimeError: if ``google-auth`` is missing or the credentials cannot
            be loaded/refreshed — with a message the agent can surface verbatim.
    """
    if scopes is None:
        scopes = [CLOUD_PLATFORM_SCOPE]

    try:
        from google.auth.transport.requests import Request
        from google.oauth2 import service_account
    except ImportError as exc:  # pragma: no cover - depends on optional dep
        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."

View on GitHub (pinned to 95e1c3d0ab)