skip to Main Content

I have a scheduled function (scheduledFunction) that calls another function (_clearOldReports) that uses a collectionGroup to regularly delete documents from any collection named reports.

In the GCP console logs viewer I am getting Error: 9 FAILED_PRECONDITION but no further details that are useful for troubleshooting the problem. This function has worked in the past, so I’m not sure what’s changed.

The Logs Explorer view in GCP console is quite difficult to read as the trace is spread across at least 24 different dropdown views. I haven’t been able to find a more reasonable log view.

Error: 9 FAILED_PRECONDITION: 
at callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19) 
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:357:73) 
at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:323:181) 
at /workspace/node_modules/@grpc/grpc-js/build/src/resolving-call.js:94:78 
at process.processTicksAndRejections (node:internal/process/task_queues:77:11)

I do not know what to try as this function has been in place and working for years now. Only the Node version has changed, now at v20. All of our functions are V1/1st Gen.

exports.scheduledFunction = functions.pubsub
  .schedule("every 30 minutes")
  .onRun(async () => {
    return Promise.all([_clearOldDocuments()]);
  });

async function _clearOldDocuments() {
  const date = Date.now() - 600000; // 10 min
  const reports = await admin
    .firestore()
    .collectionGroup("reports")
    .where("generateDate", "<", date)
    .get();
  const batch = admin.firestore().batch();
  reports.forEach((d) => batch.delete(d.ref));
  await batch.commit();
}

2

Answers


  1. Chosen as BEST ANSWER

    The fix turned out to be creating an index in the Firestore console. Many S.O. posts related to the error supported that, but the logs that were visible to me in the GCP console did not have the expected detail pointing there. In addition this has been working for quite some time without those indices having been created. I'm not sure what changed.

    I created a "Single Field" index: Collection ID: "reports" fieldPath: "generateDate" with Collection group scope set to enable both "Ascending" & "Descending"


  2. can you just quickly try the following ?

        exports.scheduledFunDeleteOldReports = functions.pubsub
           .schedule('("every 30 minutes"')
           .onRun(async (context) => {
            const date = Date.now() - 600000;
            const reportsRef = admin.firestore().collection('reports');
            const querySnapshot = await reportsRef.where('generateDate', '<', date).get();
        
            const batch = admin.firestore().batch();
            querySnapshot.forEach((doc) => {
                batch.delete(doc.ref);
            });
        
            return batch.commit();
        });
    

    see delete-data#collections

    other then that i think it will be better and efficient if you don’t use Promise.all() for this single async operation.

    exports.scheduledFunction = functions.pubsub
      .schedule("every 30 minutes")
      .onRun(async () => {
        return _clearOldDocuments();
      });
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search