Skip to content

fix(deps): patch gaxios to use globalThis.fetch on Node.js 18+ (fixes #32245)#33116

Open
whongj wants to merge 1 commit intoopenclaw:mainfrom
whongj:fix/gaxios-node22-globalthis-fetch
Open

fix(deps): patch gaxios to use globalThis.fetch on Node.js 18+ (fixes #32245)#33116
whongj wants to merge 1 commit intoopenclaw:mainfrom
whongj:fix/gaxios-node22-globalthis-fetch

Conversation

@whongj
Copy link

@whongj whongj commented Mar 3, 2026

Summary

Fixes #32245Cannot convert undefined or null to object on all Vertex AI embedded runs (Node.js v22+).


Root Cause

gaxios 7.1.x decides which fetch implementation to use in its private static #getFetch():

static async #getFetch() {
    const hasWindow = typeof window !== "undefined" && !!window;
    this.#fetch ||= hasWindow
        ? window.fetch
        : (await import("node-fetch")).default;  // ← crashes Node.js v22.22.0
    return this.#fetch;
}

In a Node.js environment, window is undefined, so it falls back to await import("node-fetch"). On Node.js v22.22.0, this dynamic ESM import of node-fetch v3.3.2 crashes the ESM module loader:

TypeError: Cannot convert undefined or null to object
    at hasOwnProperty (<anonymous>)
    at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:213:12)
    at ModuleJob.run (node:internal/modules/esm/module_job:343:25)

This crashes google-auth-library JWT token exchange before any Vertex AI API call is made, causing every Vertex-backed embedded run to fail with:

embedded run agent end: isError=true error=Cannot convert undefined or null to object

Node.js v18+ ships native fetch as globalThis.fetch. gaxios never checks for it.


Fix

A one-liner postinstall script (scripts/patch-gaxios-node22.mjs) that idempotently patches gaxios/build/cjs/src/gaxios.js:

- : (await import("node-fetch")).default;
+ : (typeof globalThis.fetch === "function" ? globalThis.fetch : (await import("node-fetch")).default);

The script:

  • Is a no-op if already patched or if gaxios has been updated upstream
  • Runs via postinstall in package.json
  • Prints a clear status message on each install

Verification

# Before patch: fails
node -e "const { JWT } = require(google-auth-library); ..."
# → Error: Cannot convert undefined or null to object

# After patch: succeeds  
node -e "const { JWT } = require(google-auth-library); ..."
# → ✅ Token OK: ya29.c.c0AZ4bNp...

All Vertex AI models (gemini-3-flash-preview, gemini-2.0-flash, etc.) resume working normally.


Notes

  • The proper long-term fix is upstream in googleapis/gaxios — a PR has been filed there
  • This postinstall patch is the shortest path to unblocking affected users on Node.js v22+
  • Tested on: Node.js v22.22.0, Debian 12, OpenClaw 2026.3.2

gaxios 7.1.x checks for `window` to decide whether to use native fetch.
In Node.js (no `window`), it falls back to `await import('node-fetch')`.
On Node.js v22.22.0, this dynamic ESM import crashes the module loader:

  TypeError: Cannot convert undefined or null to object
      at ModuleWrap.<anonymous> (node:internal/modules/esm/translators:213:12)

This kills `google-auth-library` JWT token exchange before any Vertex AI
call is made, causing ALL Vertex-backed embedded runs to fail with:

  embedded run agent end: isError=true error=Cannot convert undefined or null to object

Node.js 18+ ships native `fetch` as `globalThis.fetch`. The fix is a
one-liner: check `globalThis.fetch` before attempting the broken ESM import.

The postinstall script `scripts/patch-gaxios-node22.mjs` applies this
patch idempotently after `npm install`. It is a no-op if gaxios has been
fixed upstream or if the pattern has changed.

Fixes: openclaw#32245
Upstream issue: googleapis/gaxios (pending PR)
Copy link

@chatgpt-codex-connector chatgpt-codex-connector bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 369ac04eb2

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


const content = fs.readFileSync(gaxiosPath, "utf8");

const BROKEN = ": (await import('node-fetch')).default;";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Match gaxios import string before patching

The patcher never applies on the affected gaxios@7.1.3 builds because BROKEN looks for import('node-fetch') (single quotes), while the compiled file uses import("node-fetch") in #getFetch(); this makes content.includes(BROKEN) false and exits with "Pattern not found", so installs remain vulnerable to the Node 22 crash this commit is intended to fix.

Useful? React with 👍 / 👎.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 3, 2026

Greptile Summary

This PR adds a postinstall script that patches gaxios@7.1.3 to prefer globalThis.fetch (available natively since Node.js 18) over a dynamic import('node-fetch') that crashes the ESM loader on Node.js v22+.

The core fix logic is sound and addresses a real blocker for Vertex AI embedded runs on Node.js v22+. The idempotency checks (already patched, pattern not found) are well-thought-out.

One minor cleanup: the path module is imported but unused and should be removed to avoid lint warnings.

Confidence Score: 4/5

  • Safe to merge after removing the unused import. The patch is idempotent and benign.
  • The fix correctly addresses the Node.js v22+ ESM loader crash and is properly guarded with idempotency checks. Only a minor code cleanliness issue remains (unused import). The patch itself is beneficial and does not introduce functional risks.
  • scripts/patch-gaxios-node22.mjs — remove unused path import

Last reviewed commit: 369ac04

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

* Fix: https://github.com/googleapis/gaxios/issues/<upstream>
*/
import fs from "node:fs";
import path from "node:path";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

path is imported but never referenced in the script. Remove unused import:

Suggested change
import path from "node:path";
import { createRequire } from "node:module";
Prompt To Fix With AI
This is a comment left during a code review.
Path: scripts/patch-gaxios-node22.mjs
Line: 10

Comment:
`path` is imported but never referenced in the script. Remove unused import:

```suggestion
import { createRequire } from "node:module";
```

How can I resolve this? If you propose a fix, please make it concise.

@cgdusek

This comment was marked as spam.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

scripts Repository scripts size: XS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Vertex embedded runs fail with "Cannot convert undefined or null to object" on v2026.3.1 (Telegram + cron)

2 participants