Your gcloud login works. Your Python doesn’t. Here’s why.
Why gcloud auth login works in your terminal while Vertex AI fails in Python, and the four commands that fix Application Default Credentials (ADC).
The most common Vertex AI problem we get pulled into isn’t the model or the prompts. It’s a senior developer whose terminal talks to Google Cloud without complaint, and whose Python script falls over on the first API call. It’s nearly always the same cause, and four commands fix it.
Two logins, two files
gcloud auth login signs in the CLI. It keeps your credentials in gcloud’s own store under ~/.config/gcloud (a SQLite database, credentials.db). The Vertex AI client libraries never look there.
Client libraries use Application Default Credentials (ADC), which expects a separate JSON file at ~/.config/gcloud/application_default_credentials.json. If you’ve only run the first login, that file doesn’t exist. The auth library walks its search path, finds nothing, and throws DefaultCredentialsError.
gcloud CLI ──> credentials.db ──┐
├──> aiplatform.googleapis.com
Python SDK ──> application_default_credentials.json ──┘
Same machine, same person, two different identities as far as Google is concerned. Once you see it that way the fix is obvious.
The four commands
Run these on every developer machine, in this order:
# 1. Sign in the CLI
gcloud auth login
# 2. Set the project first, so the next step picks it up
gcloud config set project YOUR_PROJECT_ID
# 3. Create the ADC file the client libraries read
gcloud auth application-default login
# 4. Pin the quota project into the ADC file
gcloud auth application-default set-quota-project YOUR_PROJECT_ID
Step 4 is the one people skip. When you call Vertex AI with your own user credentials, Google needs to know which project to bill and count quota against. Recent gcloud versions will often set this during step 3 if a project is already configured, but I run it explicitly anyway. It costs nothing and it kills the “requires a quota project” error before anyone has to Google it.
Install gcloud properly
Pick one install method for the whole team and stick to it. Curl-to-bash installers on every laptop is how you end up with six versions of gcloud and a Slack thread nobody can follow.
macOS: use Homebrew.
brew install --cask gcloud-cli
Brew prints the path.zsh.inc and completion.zsh.inc lines to add to ~/.zshrc at the end of the install. Use the paths it gives you rather than copying them from a blog (including this one), because they differ between Apple Silicon and Intel Macs.
Debian and Ubuntu: don’t use apt-key add. It’s deprecated and trusts the key for every repo on the system. Give Google’s key its own keyring and scope it to Google’s repo:
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates gnupg curl
sudo mkdir -p /etc/apt/keyrings
curl https://packages.cloud.google.com/apt/doc/apt-key.gpg \
| sudo gpg --dearmor -o /etc/apt/keyrings/cloud.google.gpg
echo 'deb [signed-by=/etc/apt/keyrings/cloud.google.gpg] https://packages.cloud.google.com/apt cloud-sdk main' \
| sudo tee /etc/apt/sources.list.d/google-cloud-sdk.list
sudo apt-get update && sudo apt-get install -y google-cloud-cli
Get the region right
Vertex AI is regional. If your endpoint lives in europe-west4 and your client points at us-central1, you won’t get a helpful error. You’ll get a 404 and a lost afternoon.
For gcloud ai commands, the setting that matters is ai/region, not compute/region (which Vertex ignores):
gcloud config set ai/region us-central1
In code, the location you pass to the client is what counts. For Gemini calls with no residency requirement, Google recommends the global endpoint. Most of our clients in Australia have data that needs to stay onshore, so check the model you want is offered in australia-southeast1 before you build around it.
Prove it works before handing it over
Run this before anyone starts building. It confirms ADC resolves, the location is right and the account has permission to call a model.
pip install google-genai
import sys
from google import genai
PROJECT_ID = "YOUR_PROJECT_ID"
LOCATION = "global" # or the region your data has to stay in
MODEL = "gemini-3.8-flash" # or "gemini-4-argon" / "gemini-3.5-flash-lite"
def main():
try:
client = genai.Client(vertexai=True, project=PROJECT_ID, location=LOCATION)
response = client.models.generate_content(
model=MODEL,
contents="Connectivity test. Reply with: Connection OK.",
)
print(response.text.strip())
except Exception as e:
print(f"Failed: {e}", file=sys.stderr)
sys.exit(1)
if __name__ == "__main__":
main()
If your code still imports vertexai.generative_models, move it to the Google Gen AI SDK shown above. Google deprecated that module in 2025, and new projects shouldn’t start on it. Likewise, if your scripts still point at gemini-2.5-flash or gemini-2.5-pro, move them to gemini-3.8-flash, gemini-3.5-flash-lite, or gemini-4-argon.
No service account keys in CI. None.
A service account JSON key sitting in GitHub secrets is the thing I’d remove first in almost any environment we audit. Keys get committed by accident, baked into Docker layers and copied onto laptops “just for testing”. They also don’t expire unless somebody remembers to rotate them, and nobody remembers.
Use Workload Identity Federation instead. GitHub Actions gets a short-lived OIDC token for the job, Google’s Security Token Service swaps it for Google credentials, and nothing long-lived ever exists.
GitHub Actions job ──OIDC token──> Workload Identity pool ──> Service account (roles/aiplatform.user) ──> Vertex AI
name: Vertex AI deploy
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
id-token: write # required to request the OIDC token
contents: read
steps:
- uses: actions/checkout@v4
- name: Authenticate to Google Cloud
uses: google-github-actions/auth@v3
with:
workload_identity_provider: 'projects/123456789012/locations/global/workloadIdentityPools/github-pool/providers/github'
service_account: 'vertex-deployer@YOUR_PROJECT_ID.iam.gserviceaccount.com'
- name: Set up gcloud
uses: google-github-actions/setup-gcloud@v3
- name: Check Vertex AI access
run: gcloud ai endpoints list --region=us-central1
Lock the provider’s attribute condition to your own repo. A pool that trusts any GitHub repository is worse than the key you just deleted.
The checklist
gcloudinstalled throughbreworapt, same method across the teamgcloud auth logindone- ADC file created with
gcloud auth application-default login - Quota project set in ADC
aiplatform.googleapis.comenabled on the projectroles/aiplatform.useron the principal, not Owner or Editor- Client location matches where the model or endpoint actually lives
.gitignorecovers*credentials*.jsonand your virtualenv- Zero service account keys in CI, Workload Identity Federation only, scoped to your repo
If you want the Terraform for the Workload Identity pool and IAM bindings, get in touch and we’ll send it over.
Founder of Aviato Consulting and former Google Cloud Consulting Lead for APAC, specialising in enterprise cloud architecture, APRA CPS 234 and agentic AI.
Related Articles
Governing AI at Scale in Financial Services
Banks and insurers have proven AI works. The next question is whether they can run thousands of agents and still show a regulator exactly what each one did. A seven control framework and a 90 day plan for APRA, MAS, RBI and BNM expectations on Google Cloud.
How to Enforce Enterprise API Standards on a Tiered Budget
How a tiered API quality framework keeps five core engineering principles fixed while infrastructure scales across enterprise, startup and MVP budgets.
Video Post: Google Cloud Vertex AI & Hugging Face
Too many AI models to compare? How we test Gemini, Llama, Claude and Hugging Face models side by side on Vertex AI to find the best result at the best price.