Nodejs-pubsub: TypeError: channelCredentials._equals is not a function

Created on 5 Dec 2019  路  9Comments  路  Source: googleapis/nodejs-pubsub

This issue occurs on versions 1.1.2 and later.

When attempting to publish a message to the emulator, I'm getting the following error:

TypeError: channelCredentials._equals is not a function

Function to re-create error:

const pub = async (topicName, data) => {
  const options = {
    keyFilename,
    projectId
  };
  if (process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'test') {
    options.apiEndpoint = 'emulator:8085';
  }
  const pubsub = new PubSub(options);
  const stringifiedData = JSON.stringify(data);
  const dataBuffer = await Buffer.from(stringifiedData);

  const topic = `projects/${projectId}/topics/${topicName}`;

  return pubsub
    .topic(topic)
    .publish(dataBuffer)
    .then((response) => {
      logger.info('Message published.', response);
      return {
        success: true
      };
    })
    .catch((error) => {
      logger.error('Failed to publish topic', error);
      return {
        success: false
      };
    });
};

Dockerfile of emulator:

FROM google/cloud-sdk:alpine

LABEL maintainer="LADbible Group"

RUN apk --update add openjdk7-jre
RUN gcloud components install --quiet beta pubsub-emulator
RUN gcloud components update
RUN mkdir -p /var/pubsub

VOLUME /var/pubsub

EXPOSE 8085

CMD [ "gcloud", "beta", "emulators", "pubsub", "start", "--data-dir=/var/pubsub", "--host-port=0.0.0.0:8085", "--log-http", "--verbosity=debug", "--user-output-enabled" ]

Environment details

  • OS: alpine
  • Node.js version: 10.15.0
  • npm version: 6.5.0
  • @google-cloud/pubsub version: 1.1.2+
pubsub p2 bug

Most helpful comment

Found the same when attempting to connect to the emulator. Latest version of both the emulator and this library.

All 9 comments

@davemason-ladbible thanks for the write up! Any chance you could provide us with a stack trace?

@callmehiphop Sure, here you are:

TypeError: channelCredentials._equals is not a function
          at SubchannelPool.getOrCreateSubchannel (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/subchannel-pool.ts:132:32)
          at Object.createSubchannel (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/channel.ts:139:36)
          at Object.createSubchannel (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/resolving-load-balancer.ts:249:42)
          at subchannels.latestAddressList.map.address (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/load-balancer-pick-first.ts:336:33)
          at Array.map (<anonymous>)
          at PickFirstLoadBalancer.connectToAddressList (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/load-balancer-pick-first.ts:335:47)
          at PickFirstLoadBalancer.updateAddressList (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/load-balancer-pick-first.ts:386:12)
          at Object.onSuccessfulResolution (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/resolving-load-balancer.ts:210:34)
          at pendingResultPromise.then (/app/node_modules/google-gax/node_modules/@grpc/grpc-js/src/resolver-dns.ts:269:25)

Interesting, @murgatroid99 any thoughts on this?

My best guess from that error is that a Client or Channel is being created with a bad channelCredentials argument. It could be some other kind of object, or a ChannelCredentials object from the grpc library or an older version of @grpc/grpc-js. I don't immediately see anything in that code that would cause that.

Found the same when attempting to connect to the emulator. Latest version of both the emulator and this library.

Found the same when attempting to create a new subscription wihtin the emulator. Topic creation is ok. Versions:

I'm going to put this on my list of stuff to retry shortly. I suspect some changes have happened to the emulator itself, because some of the problems I've tried to reproduce weren't happening for me. Also grpc-js has changed a lot. I see that some are using gRPC C++, though, so grpc-js updates wouldn't help with that.

@feywind If the issue isn't resolved with the new version of grpc-js (and it's still an issue with the emulator) let's kick it to @kamalaboulhosn for guidance on ownership.

I finally got a chance to try this out myself. I did have to make a few tweaks to make it works, so maybe this will help.

This is my Dockerfile, based on the original, but with an updated openjdk:

FROM google/cloud-sdk:alpine

RUN apk --update add openjdk11-jre-headless
RUN gcloud components install --quiet beta pubsub-emulator
RUN gcloud components update
RUN mkdir -p /var/pubsub

VOLUME /var/pubsub

EXPOSE 8085

CMD [ "gcloud", "beta", "emulators", "pubsub", "start", "--data-dir=/var/pubsub", "--host-port=0.0.0.0:8085", "--log-http", "--verbosity=debug", "--user-output-enabled" ]

This fixed a Java exception in the emulator for not finding the Duration class.

This is the sample code:

const PubSub = require('@google-cloud/pubsub').PubSub;

const pub = async (topicName, data) => {
  const options = {
    projectId: 'testproject',
    apiEndpoint: 'localhost:8085'
  };
  const pubsub = new PubSub(options);
  const stringifiedData = JSON.stringify(data);
  const dataBuffer = await Buffer.from(stringifiedData);

  const topicId = `projects/${options.projectId}/topics/${topicName}`;

  const topic = pubsub.topic(topicId);
  const exists = await topic.exists();
  if (!exists[0]) {
    await topic.create();
    console.log('created topic');
  }

  let sub = pubsub.subscription('testsub');
  const subExists = await sub.exists();
  if (!subExists[0]) {
    await topic.createSubscription('testsub');
    console.log('created sub');
    sub = topic.subscription('testsub');
  }

  const receivePromise = new Promise(r => {
    sub.on('message', message => {
      console.log('Message received', message.data.toString());
      message.ack();
      r();
    });
  });

  const response = await topic.publish(dataBuffer);
  console.log('Message published', response);

  await receivePromise;
};

pub('testtopic2', { test: 'test' }).then(() => {
  console.log('Exiting');
  process.exit(0);
}).catch(e => {
  console.error('Error', e);
});

This is the package.json:

{
    "name": "example",
    "version": "1.0.0",
    "description": "",
    "dependencies": {
        "@google-cloud/pubsub": "^2.0.0"
    }
}

And I'm getting this output:

Message published 4
Message received {"test":"test"}
Exiting

So I think this has been fixed by subsequent grpc updates or other changes. @willianw Your subscriber issue might be fixed by updating the JDK in the Docker image?

Please feel free to re-open if there are still problems!

Was this page helpful?
0 / 5 - 0 ratings