openclaw - ✅(Solved) Fix google-vertex provider: "<authenticated>" sentinel passed as API key breaks ADC auth [2 pull requests, 2 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#50053Fetched 2026-04-08 00:59:47
View on GitHub
Comments
2
Participants
2
Timeline
6
Reactions
0
Author
Timeline (top)
commented ×2cross-referenced ×2referenced ×1subscribed ×1

Root Cause

  1. pi-ai's getEnvApiKey("google-vertex") returns "<authenticated>" as a sentinel value when GOOGLE_APPLICATION_CREDENTIALS + GOOGLE_CLOUD_PROJECT + GOOGLE_CLOUD_LOCATION are all set.
  2. OpenClaw's resolveApiKeyForProvider calls resolveEnvApiKey("google-vertex") → gets { apiKey: "<authenticated>", source: "gcloud adc" }.
  3. This gets passed as options.apiKey to pi-ai's streamGoogleVertex handler.
  4. The handler's resolveApiKey(options) sees a truthy apiKey → calls createClientWithApiKey("<authenticated>") instead of createClient() (which would use ADC).
  5. The @google/genai SDK sends "<authenticated>" as the API key to Vertex AI → 401 CREDENTIALS_MISSING.

Fix Action

Workaround

Two changes are needed:

1. Set auth: "oauth" on the google-vertex provider in openclaw.json:

{
  "google-vertex": {
    "models": [...],
    "baseUrl": "https://aiplatform.googleapis.com",
    "auth": "oauth"
  }
}

2. Patch pi-ai's resolveApiKey in node_modules/@mariozechner/pi-ai/dist/providers/google-vertex.js:

// Original:
function resolveApiKey(options) {
    return options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
}

// Patched:
function resolveApiKey(options) {
    const _k = options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
    return (_k && !_k.startsWith("<")) ? _k : undefined;
}

PR fix notes

PR #50123: fix(auth): filter pi-ai "<authenticated>" sentinel for google-vertex

Description (problem / solution / changelog)

Problem

pi-ai's getEnvApiKey("google-vertex") returns the literal string "<authenticated>" as a sentinel when ADC environment variables (GOOGLE_APPLICATION_CREDENTIALS, GOOGLE_CLOUD_PROJECT, GOOGLE_CLOUD_LOCATION) are set. OpenClaw's resolveEnvApiKey treated this as a real API key and passed it downstream, causing the Google GenAI SDK to attempt API key auth with "<authenticated>" instead of using Application Default Credentials (ADC).

Result: 401 CREDENTIALS_MISSING errors for all google-vertex requests when using service account auth.

Fix

Filter out sentinel values (strings starting with <) returned by getEnvApiKey for the google-vertex provider. When filtered, resolveEnvApiKey returns null, allowing the auth flow to fall through to ADC-based authentication.

Fixes #50053

Changed files

  • src/agents/model-auth.ts (modified, +1/-1)

PR #50320: Fix priority regressions in export attachments auth and denyCommands

Description (problem / solution / changelog)

Summary

  • fix export session HTML token injection by supporting both plain and formatted script placeholders
  • normalize HEIC and HEIF chat attachments to JPEG before prompt image upload
  • treat google-vertex ADC sentinel as oauth mode and do not pass it as apiKey
  • add config set warnings for gateway.nodes.denyCommands unknown or pattern-like entries
  • add regression tests for all four fixes

Linked issues

  • closes #49957
  • closes #50081
  • closes #50053
  • closes #50011

Validation

  • pnpm test src/auto-reply/reply/export-html/template.security.test.ts src/gateway/chat-attachments.test.ts src/agents/model-auth.test.ts src/cli/config-cli.test.ts
  • pnpm check and pnpm tsgo still report existing unrelated repo-wide TypeScript errors

Changed files

  • src/agents/model-auth.test.ts (modified, +32/-0)
  • src/agents/model-auth.ts (modified, +20/-0)
  • src/auto-reply/reply/commands-export-session.ts (modified, +22/-6)
  • src/auto-reply/reply/export-html/template.security.test.ts (modified, +10/-1)
  • src/cli/config-cli.test.ts (modified, +49/-0)
  • src/cli/config-cli.ts (modified, +152/-0)
  • src/gateway/chat-attachments.test.ts (modified, +46/-0)
  • src/gateway/chat-attachments.ts (modified, +35/-2)

Code Example

{
  "google-vertex": {
    "models": [...],
    "baseUrl": "https://aiplatform.googleapis.com",
    "auth": "oauth"
  }
}

---

// Original:
function resolveApiKey(options) {
    return options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
}

// Patched:
function resolveApiKey(options) {
    const _k = options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
    return (_k && !_k.startsWith("<")) ? _k : undefined;
}
RAW_BUFFERClick to expand / collapse

Bug Description

When using the google-vertex provider with Application Default Credentials (ADC) via a service account, OpenClaw passes the literal string "<authenticated>" as options.apiKey to the pi-ai stream handler, which then tries to use it as an actual API key instead of falling through to ADC.

Root Cause

  1. pi-ai's getEnvApiKey("google-vertex") returns "<authenticated>" as a sentinel value when GOOGLE_APPLICATION_CREDENTIALS + GOOGLE_CLOUD_PROJECT + GOOGLE_CLOUD_LOCATION are all set.
  2. OpenClaw's resolveApiKeyForProvider calls resolveEnvApiKey("google-vertex") → gets { apiKey: "<authenticated>", source: "gcloud adc" }.
  3. This gets passed as options.apiKey to pi-ai's streamGoogleVertex handler.
  4. The handler's resolveApiKey(options) sees a truthy apiKey → calls createClientWithApiKey("<authenticated>") instead of createClient() (which would use ADC).
  5. The @google/genai SDK sends "<authenticated>" as the API key to Vertex AI → 401 CREDENTIALS_MISSING.

Expected Behavior

When ADC credentials are configured for google-vertex, the handler should use new GoogleGenAI({ vertexai: true, project, location }) (the ADC path), not pass a sentinel string as an API key.

Workaround

Two changes are needed:

1. Set auth: "oauth" on the google-vertex provider in openclaw.json:

{
  "google-vertex": {
    "models": [...],
    "baseUrl": "https://aiplatform.googleapis.com",
    "auth": "oauth"
  }
}

2. Patch pi-ai's resolveApiKey in node_modules/@mariozechner/pi-ai/dist/providers/google-vertex.js:

// Original:
function resolveApiKey(options) {
    return options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
}

// Patched:
function resolveApiKey(options) {
    const _k = options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
    return (_k && !_k.startsWith("<")) ? _k : undefined;
}

Suggested Fix

Either:

  • In OpenClaw: Check if the resolved apiKey is the "<authenticated>" sentinel before passing it to the stream handler. If so, pass undefined instead, or pass a separate flag like { useAdc: true }.
  • In pi-ai: Have streamGoogleVertex check for the sentinel in resolveApiKey and treat it as "no key" (falling through to ADC).
  • Ideally both: The sentinel pattern is fragile. A dedicated auth mode field would be more robust.

Additional Context

  • auth: "oauth" on the provider config is supposed to skip API key resolution (via resolveProviderAuthOverride), but resolveApiKeyForProvider still calls resolveEnvApiKey() even when authOverride === "oauth". The override only blocks aws-sdk and resolveSyntheticLocalProviderAuth.
  • The api field cannot be set to "google-vertex" (schema enum doesn't include it), but omitting it works because OpenClaw infers the handler from the provider name.
  • The "<authenticated>" sentinel is also used for amazon-bedrock — same issue may exist there.

Environment

  • OpenClaw 2026.3.13
  • pi-ai (bundled version)
  • macOS (arm64)
  • Service account auth via GOOGLE_APPLICATION_CREDENTIALS

extent analysis

Fix Plan

To resolve the issue, we need to modify the resolveApiKey function in pi-ai to handle the "<authenticated>" sentinel value. We will also update the openclaw.json configuration to include the auth field.

Step 1: Update openclaw.json

Add the auth field to the google-vertex provider:

{
  "google-vertex": {
    "models": [...],
    "baseUrl": "https://aiplatform.googleapis.com",
    "auth": "oauth"
  }
}

Step 2: Patch pi-ai's resolveApiKey

Update the resolveApiKey function in node_modules/@mariozechner/pi-ai/dist/providers/google-vertex.js:

// Original:
function resolveApiKey(options) {
    return options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
}

// Patched:
function resolveApiKey(options) {
    const apiKey = options?.apiKey || process.env.GOOGLE_CLOUD_API_KEY;
    return (apiKey && !apiKey.startsWith("<")) ? apiKey : undefined;
}

Alternative: Update OpenClaw

Alternatively, you can update OpenClaw to check for the "<authenticated>" sentinel before passing it to the stream handler. This can be done by modifying the resolveApiKeyForProvider function to return undefined when the sentinel is detected.

Verification

To verify the fix, restart your application and check for any authentication errors. You can also add logging statements to the resolveApiKey function to ensure it is returning the expected value.

Extra Tips

  • Consider updating both OpenClaw and pi-ai to use a dedicated auth mode field instead of the sentinel pattern.
  • Be aware that the "<authenticated>" sentinel is also used for amazon-bedrock, so you may need to apply similar fixes for that provider as well.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING