Skip to content

Spanner: connection fails with "Cannot find module 'google-gax'" — bundle calls require.resolve() but extension ships no node_modules #1198

Description

@mathewhany

Bug Description

Connecting to Cloud Spanner fails immediately with Cannot find module 'google-gax'.

The vendored Spanner driver (out/vendor/@google-cloud/spanner.js) is bundled, but it contains one call that esbuild cannot inline — it resolves the google-gax package on disk to locate the shared .proto files:

Sje = AW.join(AW.dirname(require.resolve("google-gax")), "..", "protos")

(This comes from @google-cloud/common-grpc's GrpcService, and it runs at module-evaluation time, so it throws before any connection is attempted.)

The extension ships no node_modules directory at all, so require.resolve("google-gax") has nothing to find. require.resolve is a runtime filesystem lookup and is not rewritten by the bundler the way require() is.

This is the only require.resolve of a third-party package in the Spanner bundle — every other vendored driver is self-contained:

$ grep -o 'require\.resolve("[^"]*")' out/vendor/@google-cloud/spanner.js | sort | uniq -c
   1 require.resolve("google-gax")

$ ls ~/.cursor/extensions/dbcode.dbcode-1.36.8-universal/node_modules
ls: no such file or directory

Repro steps

  1. Create a new Cloud Spanner connection (auth: Application Default Credentials).
  2. Click Connect.
  3. Connection fails instantly with the error below.

Expected Behavior

The Spanner connection opens, or at least fails on something credential/network related.

Actual Behavior

It fails at driver load time with Cannot find module 'google-gax'. Nothing Spanner-specific is ever reached, so no Spanner connection can be made at all in this version.

Environment

  • DBCode version: 1.36.8 (universal)
  • VS Code (or fork) version: Cursor 3.14.27
  • OS: macOS 26.5.2 (arm64)
  • Database: Google Cloud Spanner
  • Connection: direct (Application Default Credentials)

Error Meesages (if applicable)

Cannot find module 'google-gax'
Require stack:
- /Users/<user>/.cursor/extensions/dbcode.dbcode-1.36.8/...

Suggested fix

Either of:

  1. Ship google-gax unbundled next to the extension so the resolve succeeds — only its build/protos/ directory is actually needed at runtime, since everything else is already inside the bundle.
  2. Patch the expression at build time (esbuild define, or an onLoad plugin) to point protosDir at a protos folder you copy into out/ yourself.

Workaround (confirmed working)

Dropping the real package where Node's resolution walk finds it fixes it — 476 KB, no rebuild needed:

EXT=~/.cursor/extensions/dbcode.dbcode-1.36.8-universal
npm pack google-gax@5.0.6
mkdir -p "$EXT/node_modules/google-gax"
tar -xzf google-gax-5.0.6.tgz -C "$EXT/node_modules/google-gax" --strip-components=1

Then reload the window. 5.0.6 is the version already embedded in the bundle's vendored package.json, and its main (build/src/index.js) makes the ../protos path land on build/protos/, which is where the shipped .proto files live.

(An extension update wipes this, so it needs a real fix in the build.)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions