Error trying to set auto back up Firestore, cloud function

Viewed 378

I am following this tutorial here: Tutorial

everything seems ok and it allows me to do everything in the tutorial, but when I run the function I get this error.

textPayload: "TypeError: Cannot read property 'charCodeAt' of undefined
    at peg$parsetemplate (/workspace/node_modules/google-gax/build/src/pathTemplateParser.js:304:17)
    at Object.peg$parse [as parse] (/workspace/node_modules/google-gax/build/src/pathTemplateParser.js:633:18)
    at new PathTemplate (/workspace/node_modules/google-gax/build/src/pathTemplate.js:55:54)
    at segments.forEach.segment (/workspace/node_modules/google-gax/build/src/pathTemplate.js:120:29)
    at Array.forEach (<anonymous>)
    at PathTemplate.render (/workspace/node_modules/google-gax/build/src/pathTemplate.js:114:23)
    at FirestoreAdminClient.databasePath (/workspace/node_modules/@google-cloud/firestore/build/src/v1/firestore_admin_client.js:904:57)
    at exports.scheduledFirestoreExport (/workspace/index.js:13:31)
    at Promise.resolve.then (/layers/google.nodejs.functions-framework/functions-framework/node_modules/@google-cloud/functions-framework/build/src/invoker.js:330:28)
    at process._tickCallback (internal/process/next_tick.js:68:7)
insertId: "000000-8410c5c7-8304-42b6-b2b6-dd55a54e8cab"
resource: {2}
timestamp: "2020-07-11T18:14:35.981Z"
severity: "ERROR"
labels: {1}
logName: "projects/b-b-b-app/logs/cloudfunctions.googleapis.com%2Fcloud-functions"
trace: "projects/b-b-b-app/traces/d7c07a715d0106225d9963ce2a046489"
receiveTimestamp: "2020-07-11T18:14:44.813410062Z"
}

I can't see what the problem may be. I changed the buckets and the app ids like asked in the tutorial.

I am on a Blaze plan and can export the database to the bucket manually by using shell command and using

gcloud firestore export gs://bbbdata-backup

I am using the GCP console on the firebase site and using this code.

const firestore = require('@google-cloud/firestore');
const client = new firestore.v1.FirestoreAdminClient();

const bucket = 'gs://bbbdata-backup'

exports.scheduledFirestoreExport = (event, context) => {
const databaseName = client.databasePath(
process.env.GCLOUD_PROJECT,
'(default)'
);

return client
 .exportDocuments({
  name: databaseName,
  outputUriPrefix: bucket,
  // Leave collectionIds empty to export all collections
  // or define a list of collection IDs:
  // collectionIds: ['users', 'posts']
  collectionIds: [],
})
.then(responses => {
  const response = responses[0];
  console.log(`Operation Name: ${response['name']}`);
  return response;
})
.catch(err => {
  console.error(err);
});
};
2 Answers

Following the tutorial referred by the OP I run into precisely the same error. Runtime used: Node.js 14.

Root cause of the issue: value of process.env.GCLOUD_PROJECT is undefined.

Workaround: Go to GCP console -> Home. Note your Project ID. Replace process.env.GCLOUD_PROJECT with the 'Project ID' string. The Cloud Function will then work as expected

Note: it appears to be a known issue that GCLOUD_PROJECT environment variable was missing in the Node.js 10 runtime. This bug report contains a lot of additional pointers: https://github.com/firebase/firebase-functions/issues/437

I had a similar issue last year, probably you are missing some permission, I would do it this way, hope this works for you:

import * as functions from 'firebase-functions'
import { auth } from 'google-auth-library'

export const generateBackup = async () => {
  const client = await auth.getClient({
    scopes: [
      'https://www.googleapis.com/auth/datastore',
      'https://www.googleapis.com/auth/cloud-platform'
    ]
  })

  const path = `YOUR_FOLDER_NAME_FOR_THE_BACKUP`
  const BUCKET_NAME = `YOUR_BUCKET_NAME_HERE`

  const projectId = await auth.getProjectId()
  const url = `https://firestore.googleapis.com/v1beta1/projects/${projectId}/databases/(default):exportDocuments`
  const backup_route = `gs://${BUCKET_NAME}/${path}`

  return client.request({
    url,
    method: 'POST',
    data: {
        outputUriPrefix: backup_route,
        // collectionsIds: [] // if you want to specify which collections to export, none means all
    }
  })
  .catch(async (e) => {
    return Promise.reject({ message: e.message })
  })

}

You can then decide that is your trigger for this function and execute it accordingly.

Note: Go to the IAM section of your project and find the App Engine service account, you will need to add the role Cloud Datastore Import Export Admin, otherwise, It will fail.

You can read more about it here It's very detailed.

Cheers.

Related