Skip to content

google-vertex ADC auth broken: "<authenticated>" sentinel passed as literal API key → 401 #49191

@pdd-cli

Description

@pdd-cli

Bug

google-vertex models using Application Default Credentials (ADC) — via GOOGLE_APPLICATION_CREDENTIALS service account key or gcloud auth application-default login — fail with 401 UNAUTHENTICATED:

API keys are not supported by this API. Expected OAuth2 access token or other authentication credentials that assert a principal.

Root Cause

pi-ai's getEnvApiKey("google-vertex") returns the string "<authenticated>" as a sentinel when ADC environment variables are configured (GOOGLE_APPLICATION_CREDENTIALS + GOOGLE_CLOUD_PROJECT + GOOGLE_CLOUD_LOCATION). This sentinel is meant to signal "auth is available" for model discovery, but it flows into the google-vertex provider as a literal API key through two independent paths:

Path 1: openclaw's resolveEnvApiKey

resolveEnvApiKey("google-vertex") in src/agents/model-auth.ts calls getEnvApiKey("google-vertex") → returns { apiKey: "<authenticated>", source: "gcloud adc" }resolveApiKeyForProvider returns it with mode: "api-key"applyApiKeyInfo calls authStorage.setRuntimeApiKey("google-vertex", "<authenticated>").

Path 2: pi-ai's internal AuthStorage.getApiKey fallback

Even without Path 1, pi-coding-agent's AuthStorage.getApiKey("google-vertex") falls back to getEnvApiKey("google-vertex") → returns "<authenticated>" → passed as options.apiKey to the provider.

Both paths end the same way

The google-vertex provider's resolveApiKey(options) returns options.apiKey ("<authenticated>", truthy) → calls createClientWithApiKey(model, "<authenticated>") → sends x-goog-api-key: <authenticated> header → Vertex AI rejects with 401.

The correct path would be resolveApiKey returning undefinedcreateClient(model, project, location) → uses GoogleAuth with GOOGLE_APPLICATION_CREDENTIALS → real OAuth Bearer token → 200.

Breaking Commits

  1. bce62f8c0f (2026-01-05) — pi-ai upgrade to ^0.36.0 which introduced the "<authenticated>" sentinel in getEnvApiKey("google-vertex")
  2. b04c838c15e (2026-01-06) — feat!: redesign model config + auth profiles which added the resolveEnvApiKey google-vertex block that passes the sentinel through Path 1

Before these commits, getEnvApiKey("google-vertex") returned undefined, so the provider always took the ADC path.

Environment

  • Node.js 25.6.1
  • @mariozechner/pi-ai 0.58.0
  • @mariozechner/pi-coding-agent 0.58.0
  • macOS with launchd-managed gateway
  • GOOGLE_APPLICATION_CREDENTIALS pointing to a valid service account JSON key

Ideal upstream fix

The root fix belongs in @mariozechner/pi-ai: getEnvApiKey should not return "<authenticated>" from AuthStorage.getApiKey (or the google-vertex provider should recognize and strip the sentinel). Until then, openclaw needs a workaround.

Metadata

Metadata

Assignees

Labels

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions