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
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"
can you just quickly try the following ?
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.