After upgrading protobufjs from 7.5.5 → 7.5.6 (and its sub-deps @protobufjs/codegen 2.0.4→2.0.5, @protobufjs/inquire 1.1.0→1.1.1, @protobufjs/utf8 1.1.0→1.1.1), gRPC unary calls made through @google-cloud/run's JobsClient started failing with an Error whose code, details, and metadata fields are all undefined / empty. Pinning protobufjs back to 7.5.5 resolves the issue.
Environment
protobufjs: 7.5.6 (broken) / 7.5.5 (works)
@google-cloud/run: 3.2.0 (unchanged)
@grpc/grpc-js: unchanged across the regression
google-gax, google-auth-library, gaxios, gtoken: all unchanged
Node.js: (fill in your prod Node version)
Runtime: Google Cloud Run (Next.js 16 server)
Package manager: bun (lockfile-resolved)
The lockfile diff shows protobufjs and its sub-modules are the only packages in the gRPC request path that changed between the working and broken states.
Symptom
Calling JobsClient.runJob(...) produces:
Error: undefined undefined: undefined
at (.../grpc-js)
at onReceiveStatus (.../grpc-js)
at onReceiveStatus (.../grpc-js)
at onReceiveStatus (.../grpc-js)
... (gRPC client internals)
at makeUnaryRequest (.../grpc-js)
...
{
code: undefined,
details: undefined,
metadata: Metadata { internalRepr: Map(0) {}, opaqueData: Map(0) {}, options: {} }
}
The thrown ServiceError has no status code, no details, and an empty metadata map — i.e. the trailers/status frame is being decoded into empty/undefined fields rather than being parsed correctly. A normal RPC failure carries a numeric code (e.g. 7 PERMISSION_DENIED) and a details string; an auth/transport failure usually surfaces as a different bare Error. This signature is distinct from both.
Reproduction
Minimal repro:
import { JobsClient } from '@google-cloud/run'
const client = new JobsClient()
await client.runJob({
name: client.jobPath('my-project', 'us-central1', 'my-job')
})
Run on Cloud Run with protobufjs@7.5.6 resolved in the tree → throws the all-undefined error.
Pin protobufjs@7.5.5 (e.g. via "resolutions" / "overrides") → call succeeds.
Suspected cause
@google-cloud/run → google-gax → @grpc/grpc-js all rely on protobufjs to decode the gRPC trailing status frame. The fact that the decoded status object has code: undefined, details: undefined and an empty metadata Map suggests the trailer decode is silently producing an empty/zero-initialized object rather than throwing. Possibly related to the @protobufjs/codegen 2.0.4→2.0.5 or @protobufjs/utf8 1.1.0→1.1.1 patch (the latter could affect string field decoding in the status message).
Workaround
Pin protobufjs to 7.5.5:
package.json
{
"overrides": {
"protobufjs": "7.5.5"
}
}
After upgrading protobufjs from 7.5.5 → 7.5.6 (and its sub-deps @protobufjs/codegen 2.0.4→2.0.5, @protobufjs/inquire 1.1.0→1.1.1, @protobufjs/utf8 1.1.0→1.1.1), gRPC unary calls made through @google-cloud/run's JobsClient started failing with an Error whose code, details, and metadata fields are all undefined / empty. Pinning protobufjs back to 7.5.5 resolves the issue.
Environment
protobufjs: 7.5.6 (broken) / 7.5.5 (works)
@google-cloud/run: 3.2.0 (unchanged)
@grpc/grpc-js: unchanged across the regression
google-gax, google-auth-library, gaxios, gtoken: all unchanged
Node.js: (fill in your prod Node version)
Runtime: Google Cloud Run (Next.js 16 server)
Package manager: bun (lockfile-resolved)
The lockfile diff shows protobufjs and its sub-modules are the only packages in the gRPC request path that changed between the working and broken states.
Symptom
Calling JobsClient.runJob(...) produces:
Error: undefined undefined: undefined
at (.../grpc-js)
at onReceiveStatus (.../grpc-js)
at onReceiveStatus (.../grpc-js)
at onReceiveStatus (.../grpc-js)
... (gRPC client internals)
at makeUnaryRequest (.../grpc-js)
...
{
code: undefined,
details: undefined,
metadata: Metadata { internalRepr: Map(0) {}, opaqueData: Map(0) {}, options: {} }
}
The thrown ServiceError has no status code, no details, and an empty metadata map — i.e. the trailers/status frame is being decoded into empty/undefined fields rather than being parsed correctly. A normal RPC failure carries a numeric code (e.g. 7 PERMISSION_DENIED) and a details string; an auth/transport failure usually surfaces as a different bare Error. This signature is distinct from both.
Reproduction
Minimal repro:
Run on Cloud Run with protobufjs@7.5.6 resolved in the tree → throws the all-undefined error.
Pin protobufjs@7.5.5 (e.g. via "resolutions" / "overrides") → call succeeds.
Suspected cause
@google-cloud/run → google-gax → @grpc/grpc-js all rely on protobufjs to decode the gRPC trailing status frame. The fact that the decoded status object has code: undefined, details: undefined and an empty metadata Map suggests the trailer decode is silently producing an empty/zero-initialized object rather than throwing. Possibly related to the @protobufjs/codegen 2.0.4→2.0.5 or @protobufjs/utf8 1.1.0→1.1.1 patch (the latter could affect string field decoding in the status message).
Workaround
Pin protobufjs to 7.5.5:
package.json