Summary
@google-cloud/agentplatform (and its predecessor @google-cloud/vertexai) pins
@google/genai: ^1.45.0. Any application that also depends on @google/genai@^2.x
— which is the current major — gets two full copies of @google/genai installed,
because the ranges cannot dedupe.
@google/genai is ~16 MB installed, so this is ~16 MB of pure duplication, plus a second
copy of the google-auth-library stack underneath it.
Reproduction
{
"dependencies": {
"@google/genai": "^2.9.0",
"@google-cloud/vertexai": "^1.12.0"
}
}
$ npm install && du -sh node_modules
54M
$ find node_modules -type d -path '*@google/genai'
node_modules/@google/genai # 2.18.0
node_modules/@google-cloud/vertexai/node_modules/@google/genai # 1.52.0
The @google/genai pin was introduced in @google-cloud/vertexai@1.11.0 and carried into
@google-cloud/agentplatform.
Secondary effect: broken instanceof
Because the two copies are distinct module instances, classes exported from them are
distinct objects. Downstream code that catches errors originating in the nested copy cannot
use instanceof and has to match structurally instead. A real example from
google/adk-js:
// gRPC transports report NOT_FOUND as a numeric `code`; the `@google/genai` `ApiClient`
// behind the Sessions client throws an `ApiError` carrying a numeric `status` instead.
// Matched structurally, not with `instanceof`: `@google-cloud/vertexai` resolves its own
// copy of `@google/genai`, so its `ApiError` is a different class object.
This is the usual duplicate-instance failure mode and it will keep surfacing as long as two
copies can coexist.
Requested change
Either of:
- Widen the range to
^1.45.0 || ^2.0.0 if the v2 surface used here is compatible, or
- Make
@google/genai a peer dependency (optionally with peerDependenciesMeta), so
the host application controls the version and there is structurally only ever one copy.
(2) is the more robust option for a library that re-exports and re-throws types from
@google/genai, since it makes the single-instance requirement explicit rather than
incidental.
Compatibility signal
Forcing the nested copy to 2.18.0 via an npm overrides entry, the entry points a
downstream consumer typically touches all still load and construct:
OK @google-cloud/vertexai
OK @google-cloud/vertexai/build/src/genai/client.js
OK @google-cloud/vertexai/build/src/genai/sessions.js
OK @google-cloud/vertexai/build/src/genai/memories.js
OK @google-cloud/vertexai/build/src/genai/types.js
OK new Client({project, location, vertexai: true})
Install tree goes 54 MB → 39 MB. That is obviously not a full compatibility audit — v1→v2
had breaking changes — but it suggests the surface this package depends on may already be
v2-clean, or close to it.
Why downstream can't fix this properly
npm overrides are only honoured in the root project's package.json; an override
declared inside a dependency is ignored (verified). So a library that depends on both
packages cannot dedupe on behalf of its own consumers — only the end application can, and
only by adding an override it shouldn't need to know about.
Summary
@google-cloud/agentplatform(and its predecessor@google-cloud/vertexai) pins@google/genai: ^1.45.0. Any application that also depends on@google/genai@^2.x— which is the current major — gets two full copies of
@google/genaiinstalled,because the ranges cannot dedupe.
@google/genaiis ~16 MB installed, so this is ~16 MB of pure duplication, plus a secondcopy of the
google-auth-librarystack underneath it.Reproduction
{ "dependencies": { "@google/genai": "^2.9.0", "@google-cloud/vertexai": "^1.12.0" } }The
@google/genaipin was introduced in@google-cloud/vertexai@1.11.0and carried into@google-cloud/agentplatform.Secondary effect: broken
instanceofBecause the two copies are distinct module instances, classes exported from them are
distinct objects. Downstream code that catches errors originating in the nested copy cannot
use
instanceofand has to match structurally instead. A real example fromgoogle/adk-js:
This is the usual duplicate-instance failure mode and it will keep surfacing as long as two
copies can coexist.
Requested change
Either of:
^1.45.0 || ^2.0.0if the v2 surface used here is compatible, or@google/genaia peer dependency (optionally withpeerDependenciesMeta), sothe host application controls the version and there is structurally only ever one copy.
(2) is the more robust option for a library that re-exports and re-throws types from
@google/genai, since it makes the single-instance requirement explicit rather thanincidental.
Compatibility signal
Forcing the nested copy to
2.18.0via an npmoverridesentry, the entry points adownstream consumer typically touches all still load and construct:
Install tree goes 54 MB → 39 MB. That is obviously not a full compatibility audit — v1→v2
had breaking changes — but it suggests the surface this package depends on may already be
v2-clean, or close to it.
Why downstream can't fix this properly
npm
overridesare only honoured in the root project'spackage.json; an overridedeclared inside a dependency is ignored (verified). So a library that depends on both
packages cannot dedupe on behalf of its own consumers — only the end application can, and
only by adding an override it shouldn't need to know about.