I have the following cloud function:
const { Firestore, Timestamp } = require('@google-cloud/firestore');
const { ImageAnnotatorClient } = require('@google-cloud/vision');
const client = new ImageAnnotatorClient();
const projectId = "*project-id*";
const databaseId = "*database-id*";
const db = new Firestore({ projectId, databaseId });
console.log('Firestore database client:', db);
console.log("Firestore database ID: ", db.databaseId);
exports.processImage = async (event, context) => {
// Check if event data is present
if (!event || !event.name || !event.bucket) {
console.error('Invalid Cloud Storage event. Exiting.');
return;
}
const filePath = event.name;
const bucketName = event.bucket;
const fileName = filePath.split('/').pop();
// Prepare image for the Vision API
const imageUri = `gs://${bucketName}/${filePath}`;
console.log(`Calling Vision API for image: ${imageUri}`);
// Call the Vision API
try {
const [result] = await client.labelDetection(imageUri);
const labels = result.labelAnnotations.map(label => label.description);
console.log(`Labels detected: ${labels.join(', ')}`);
// Store the labels in Firestore
const docRef = db.collection('photo-ai-db').doc(fileName);
console.log(`Writing to Firestore document: ${docRef.path}`);
try {
// Set document data with merge option to create document if it doesn't exist
await docRef.update({ labels, processedAt: Timestamp.now() });
await docRef.set({ labels, processedAt: Timestamp.now() }, { merge: true });
console.log(`Processed image ${fileName} and stored labels in Firestore.`);
} catch (error) {
console.error('Error writing to Firestore:', error);
}
} catch (error) {
console.error('Error calling Vision API:', error);
}
};
This is my firestore database, I've manually created these collections because I keep getting the error below, so I thought if I created them, I might get somewhere.
The function reads from cloud storage (it seems to read correctly because the labels that are being extracted in the logs are correct). The issue is that it doesn't store the labels in firestore.
Logs:
DEFAULT 2024-03-27T05:18:24.393704Z Firestore database client: Firestore {
DEFAULT 2024-03-27T05:18:24.393731Z _settings: {
DEFAULT 2024-03-27T05:18:24.393739Z projectId: '*project-id*',
DEFAULT 2024-03-27T05:18:24.393745Z databaseId: '*database-id*',
DEFAULT 2024-03-27T05:18:24.393751Z libName: 'gccl',
DEFAULT 2024-03-27T05:18:24.393757Z libVersion: '4.15.1'
DEFAULT 2024-03-27T05:18:24.393762Z },
DEFAULT 2024-03-27T05:18:24.393768Z _settingsFrozen: false,
DEFAULT 2024-03-27T05:18:24.393774Z _serializer: Serializer {
DEFAULT 2024-03-27T05:18:24.393781Z createReference: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393787Z createInteger: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393794Z allowUndefined: false
DEFAULT 2024-03-27T05:18:24.393799Z },
DEFAULT 2024-03-27T05:18:24.393805Z _projectId: '*project-id*',
DEFAULT 2024-03-27T05:18:24.393811Z registeredListenersCount: 0,
DEFAULT 2024-03-27T05:18:24.393816Z bulkWritersCount: 0,
DEFAULT 2024-03-27T05:18:24.393823Z _backoffSettings: { initialDelayMs: 100, maxDelayMs: 60000, backoffFactor: 1.3 },
DEFAULT 2024-03-27T05:18:24.393830Z _clientPool: ClientPool {
DEFAULT 2024-03-27T05:18:24.393836Z concurrentOperationLimit: 100,
DEFAULT 2024-03-27T05:18:24.393841Z maxIdleClients: 1,
DEFAULT 2024-03-27T05:18:24.393847Z clientFactory: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393854Z clientDestructor: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393860Z activeClients: Map(0) {},
DEFAULT 2024-03-27T05:18:24.393865Z failedClients: Set(0) {},
DEFAULT 2024-03-27T05:18:24.393870Z terminated: false,
DEFAULT 2024-03-27T05:18:24.393876Z terminateDeferred: Deferred {
DEFAULT 2024-03-27T05:18:24.393882Z resolve: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393888Z reject: [Function (anonymous)],
DEFAULT 2024-03-27T05:18:24.393893Z promise: [Promise]
DEFAULT 2024-03-27T05:18:24.393899Z }
DEFAULT 2024-03-27T05:18:24.393904Z }
DEFAULT 2024-03-27T05:18:24.393910Z }
DEFAULT 2024-03-27T05:18:24.394410Z Firestore database ID: undefined
INFO 2024-03-27T05:18:24.491815Z Default STARTUP TCP probe succeeded after 1 attempt for container "worker" on port 8080.
INFO 2024-03-27T05:18:24.592803Z [protoPayload.serviceName: run.googleapis.com] [protoPayload.methodName: v1] [protoPayload.resourceName: namespaces/*project-id*/revisions/processimage-00014-yac] Ready condition status changed to True for Revision processimage-00014-yac.
INFO 2024-03-27T05:18:26.098282Z [protoPayload.serviceName: run.googleapis.com] [protoPayload.methodName: v1] [protoPayload.resourceName: namespaces/*project-id*/services/processimage] Ready condition status changed to True for Service processimage.
NOTICE 2024-03-27T05:18:26.595138638Z [protoPayload.serviceName: cloudfunctions.googleapis.com] [protoPayload.methodName: google.cloud.functions.v2.FunctionService.UpdateFunction] [protoPayload.resourceName: projects/*project-id*/locations/us-central1/functions/processimage] [protoPayload.authenticationInfo.principalEmail: [email protected]] audit_log, method: "google.cloud.functions.v2.FunctionService.UpdateFunction", principal_email: "[email protected]"
INFO 2024-03-27T05:18:32.701075Z [httpRequest.requestMethod: POST] [httpRequest.status: 204] [httpRequest.responseSize: 592 B] [httpRequest.latency: 723 ms] [httpRequest.userAgent: curl 7.74.0] https://us-central1-project-id.cloudfunctions.net/processimage
DEFAULT 2024-03-27T05:18:32.759563Z Calling Vision API for image: gs://ece9016-raw-images/teeth-label.jpg
DEFAULT 2024-03-27T05:18:33.257399Z Labels detected: Eye, Mouth, Human body, Jaw, Gesture, Ear, Font, Happy, Tooth, Drawing
DEFAULT 2024-03-27T05:18:33.258075Z Writing to Firestore document: photo-ai-db/teeth-label.jpg
DEFAULT 2024-03-27T05:18:33.435653Z Error writing to Firestore: Error: 5 NOT_FOUND:
DEFAULT 2024-03-27T05:18:33.435678Z at Object.callErrorFromStatus (/workspace/node_modules/@grpc/grpc-js/build/src/call.js:31:19)
DEFAULT 2024-03-27T05:18:33.435684Z at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:190:52)
DEFAULT 2024-03-27T05:18:33.435691Z at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:365:141)
DEFAULT 2024-03-27T05:18:33.435695Z at Object.onReceiveStatus (/workspace/node_modules/@grpc/grpc-js/build/src/client-interceptors.js:328:181)
DEFAULT 2024-03-27T05:18:33.435700Z at /workspace/node_modules/@grpc/grpc-js/build/src/call-stream.js:188:78
DEFAULT 2024-03-27T05:18:33.435705Z at process.processTicksAndRejections (node:internal/process/task_queues:77:11)
DEFAULT 2024-03-27T05:18:33.435711Z for call at
DEFAULT 2024-03-27T05:18:33.435717Z at ServiceClientImpl.makeUnaryRequest (/workspace/node_modules/@grpc/grpc-js/build/src/client.js:160:30)
DEFAULT 2024-03-27T05:18:33.435722Z at ServiceClientImpl.<anonymous> (/workspace/node_modules/@grpc/grpc-js/build/src/make-client.js:105:19)
DEFAULT 2024-03-27T05:18:33.435727Z at /workspace/node_modules/@google-cloud/firestore/build/src/v1/firestore_client.js:205:29
DEFAULT 2024-03-27T05:18:33.435732Z at /workspace/node_modules/google-gax/build/src/normalCalls/timeout.js:44:16
DEFAULT 2024-03-27T05:18:33.435737Z at repeat (/workspace/node_modules/google-gax/build/src/normalCalls/retries.js:80:25)
DEFAULT 2024-03-27T05:18:33.435742Z at /workspace/node_modules/google-gax/build/src/normalCalls/retries.js:118:13
DEFAULT 2024-03-27T05:18:33.435753Z at OngoingCallPromise.call (/workspace/node_modules/google-gax/build/src/call.js:67:27)
DEFAULT 2024-03-27T05:18:33.435758Z at NormalApiCaller.call (/workspace/node_modules/google-gax/build/src/normalCalls/normalApiCaller.js:34:19)
DEFAULT 2024-03-27T05:18:33.435764Z at /workspace/node_modules/google-gax/build/src/createApiCall.js:81:30
DEFAULT 2024-03-27T05:18:33.435768Z Caused by: Error
DEFAULT 2024-03-27T05:18:33.435774Z at WriteBatch.commit (/workspace/node_modules/@google-cloud/firestore/build/src/write-batch.js:417:23)
DEFAULT 2024-03-27T05:18:33.435780Z at DocumentReference.update (/workspace/node_modules/@google-cloud/firestore/build/src/reference.js:393:14)
DEFAULT 2024-03-27T05:18:33.435785Z at exports.processImage (/workspace/index.js:39:20) {
DEFAULT 2024-03-27T05:18:33.435789Z code: 5,
DEFAULT 2024-03-27T05:18:33.435793Z details: '',
DEFAULT 2024-03-27T05:18:33.435797Z metadata: Metadata { internalRepr: Map(0) {}, options: {} },
DEFAULT 2024-03-27T05:18:33.435803Z note: 'Exception occurred in retry method that was not classified as transient'
DEFAULT 2024-03-27T05:18:33.435807Z }

I replicated your issue with your code and found out you are trying to
updatedocuments even before they are created or exist. Hence, you are gettingError: 5 NOT\_FOUND. And you are unable to createdocumentsorcollectionsas you are stuck at error.Update
Steps I followed are :
Created
Cloud Function 2nd genusing console.Selected Trigger Type : Cloud Storage and Event Type : google.cloud.storage.object.v1.finalized
Selected inline editor and selected
node.js20runtime and added your code by making some changes as belowPackage.jsoncloud storageand finally, I can see changes infirestoreas well.