Skip to content

Type error when creating grpc client with RoundRobin load balancing policy #221

Open

Description

@aldelucca1

We are seeing the following TypeError when using @authzed/authzed-node v1.3.1 with @grpc/grpc-js v1.13.3:

TypeError: Cannot read properties of undefined (reading 'generateMetadata')
    at LoadBalancingCall.doPick (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancing-call.js:131:22)
    at Object.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/internal-channel.js:224:26)
    at ResolvingLoadBalancer.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/resolving-load-balancer.js:273:35)
    at Object.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/resolving-load-balancer.js:177:22)
    at ChildLoadBalancerHandler.ChildPolicyHelper.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancer-child-handler.js:50:50)
    at RoundRobinLoadBalancer.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancer-round-robin.js:147:35)
    at RoundRobinLoadBalancer.calculateAndUpdateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancer-round-robin.js:109:18)
    at Object.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancer-round-robin.js:87:22)
    at Object.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancer-pick-first.js:456:38)
    at PickFirstLoadBalancer.updateState (/app/node_modules/.pnpm/@grpc+grpc-js@1.13.3/node_modules/@grpc/grpc-js/build/src/load-balancer-pick-first.js:351:35)

Our client is configured with the following options:

    options = {
      'grpc.service_config': JSON.stringify({
        loadBalancingConfig: [{ round_robin: {} }],
      }),
      ...options,
    };

Our configuration was working when using @authzed/authzed-node v1.2.3 with @grpc/grpc-js v1.12.5

Activity

  1. tstirrat15 commented on Apr 18, 2025

    @tstirrat15
    Contributor

    @aldelucca1 I imagine this is related to the internals that we changed in v1.3.0. Can you show a bit more of the surrounding code? How are you setting up the client? Which field is this options object being handed to?

  2. aldelucca1 commented on Apr 18, 2025

    @aldelucca1
    Author

    Sure, we wrap the client like this

    export class Authorizer {
      #client: v1.ZedPromiseClientInterface;
      constructor(
        host: string,
        token: string,
        secure: boolean,
        options?: ClientOptions
      ) {
        options = {
          'grpc.service_config': JSON.stringify({
            loadBalancingConfig: [{ round_robin: {} }],
          }),
          ...options,
        };
        const client = v1.NewClient(
          token,
          host,
          secure
            ? v1.ClientSecurity.SECURE
            : v1.ClientSecurity.INSECURE_LOCALHOST_ALLOWED,
          PreconnectServices.PERMISSIONS_SERVICE,
          options
        );
        this.#client = client.promises;
      }
      async check(permission: Permission, subject: Objector): Promise<boolean> {
        const res = await this.#client.checkPermission(
          v1.CheckPermissionRequest.create(requestFromCheck(permission, subject))
        );
        return (
          res.permissionship ===
          v1.CheckPermissionResponse_Permissionship.HAS_PERMISSION
        );
      }
      async checkMany(checks: PermissionPair[]): Promise<(boolean | Error)[]> {
        const reqs = checks.map(({ permission, subject }) =>
          requestFromCheck(permission, subject)
        );
        const res = await this.#client.checkBulkPermissions(
          v1.CheckBulkPermissionsRequest.create({
            items: reqs,
          })
        );
        return res.pairs.map(({ response }) => {
          if (response.oneofKind === 'error') {
            return Error(response.error.message);
          } else if (response.oneofKind === 'item') {
            return (
              response.item.permissionship ===
              v1.CheckPermissionResponse_Permissionship.HAS_PERMISSION
            );
          }
          return false;
        });
      }
    }
  3. tstirrat15 commented on Apr 21, 2025

    @tstirrat15
    Contributor

    When you see this error, are you in a TLS environment?

    I added a test in #222 - does that look like your usage to you? It seems to be passing, but that also only rules out one codepath.

  4. aldelucca1 commented on Apr 21, 2025

    @aldelucca1
    Author

    We are not using TLS when we see this error

  5. coreyvanpw commented on Jul 17, 2026

    @coreyvanpw

    Is there a solution to this? I'm running into this with v1.6.1 and grpc-js@1.14.3

    Edit: never mind, this was a configuration problem masquerading as a code problem

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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