Skip to content

Regression in 7.5.6: gRPC responses decode with undefined code/details/empty metadata when used via @grpc/grpc-js / google-gax #2214

@ekansh-tdc

Description

@ekansh-tdc

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"
  }
}

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions