0
votes

I have a simple Cloud Function that receives a webhook and then does a streaming insert into BigQuery. The code is based on this sample (except that I am using streaming inserts)

exports.webHook = function webHook (req, res) {
  return Promise.resolve()
    .then(() => {
      if (req.method !== 'POST') {
        const error = new Error('Only POST requests are accepted');
        error.code = 405;
        throw error;
      }

      const events = req.body || {};
      if (events) {
        const opts = { ignoreUnknownValues: true };
        bigquery
          .dataset('config.DATASET')
          .table('config.TABLE')
          .insert(events, opts)
          .then((data) => {
            console.log(`Success: ${JSON.stringify(data[0])}`);
          })
          .catch((error) => {
            if (error.name === 'PartialFailureError') {
              console.error(`PARTIAL ERROR: ${JSON.stringify(error)}`);
              } else {
              console.error(`OTHER ERROR: ${JSON.stringify(error)}`);
            }

          });
      };
    })
    .then(() => res.status(200).end())
    .catch((err) => {
      console.error(err);
      res.status(err.code || 500).send(err);
      return Promise.reject(err);
    });
};

This function works well most of the time, but I do get the occasional authentication error, which then goes away. enter image description here

textPayload: "OTHER ERROR: {"code":401,"errors":[{"message":"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.","domain":"global","reason":"unauthorized"}],"message":"Request had invalid authentication credentials. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project."}"

I am not sure how auth could be an issue since the Cloud Function and BigQuery are all in the same project.

1
I highly recommend reporting the issue on Public Issue Tracker.Kenworth
How often do you get this error? It could be that your token is expiring.Sonya
@Sonya - the problem comes and goes away at random times and I could not point it to anything specific. Since the cloud function and other services like BigQuery are all run inside a single GCP project, auth is supposed to be handled.Michael Whitaker

1 Answers

1
votes

The folks on the Cloud Functions team think this may be due to an issue with the access token time-to-live (TTL) and suggested a workaround that has worked for me. Instead of initializing BigQuery at the top of your code (as all their examples have it), put the initializing code right inside the function that makes the call.

Do this:

exports.webHook = function webHook (req, res) {
  const bigquery = require('@google-cloud/bigquery')();
  return Promise.resolve()
    .then(() => {
      if (req.method !== 'POST') {
        const error = new Error('Only POST requests are accepted');
        error.code = 405;
        throw error;
      }
      .
      .

instead of:

const bigquery = require('@google-cloud/bigquery')();
.
.
exports.webHook = function webHook (req, res) {
      return Promise.resolve()
        .then(() => {
          if (req.method !== 'POST') {
            const error = new Error('Only POST requests are accepted');
            error.code = 405;
            throw error;
          }
          .
          .