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

    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